[JAVA] static 변수, 싱글톤

static 변수

공통으로 사용하는 변수가 필요한 경우 

● 여러 인스턴스가 공유하는 기준 값이 필요한 경우
● 학생마다 새로운 학번 생성
● 카드회사에서 카드를 새로 발급할때마다 새로운 카드 번호를 부여
● 회사에 사원이 입사할때 마다 새로운 사번이 필요한
● 은행에서 대기표를 뽑을 경우(2대 이상) 

 

static 변수 선언과 사용하기

● 선언 방법 -  static int serialNum;
● 인스턴스가 생성될 때 만들어지는 변수가 아닌, 처음 프로그램이 메모리에 로딩될 때 메모리를 할당
● 클래스 변수, 정적변수라고도 함
● 인스턴스 생성과 상관 없이 사용 가능하므로 클래스 이름으로 직접 참조
● 사용방법 - Student.serialNum = 100;

static을 활용한 예제

클래스

package ch08;

 

public class NumberPrinter {

 

private int id;

private static int waitNumber = 1; // 선언과 동시에 초기화

 

public NumberPrinter(int id) {

this.id = id;

}

 

// 번호표를 출력 합니다.

public void printwaitNumber() {

System.out.println(id + " 기기의 대기 순번은 " + waitNumber);

waitNumber++;

}

}

객체

package ch08;

 

public class NumberPrinterMainTest {

 

public static void main(String[] args) {

 

NumberPrinter numberPrinter1 = new NumberPrinter(1);

NumberPrinter numberPrinter2 = new NumberPrinter(2);

 

numberPrinter1.printwaitNumber();

numberPrinter1.printwaitNumber();

numberPrinter1.printwaitNumber();

numberPrinter1.printwaitNumber();

 

numberPrinter2.printwaitNumber();

numberPrinter2.printwaitNumber();

numberPrinter2.printwaitNumber();

 

}

 

}

결과

waitNumber 앞에 static을 쓰니까 연결되어 번호가 나오고 있다

1 기기의 대기 순번은 1

1 기기의 대기 순번은 2

1 기기의 대기 순번은 3

1 기기의 대기 순번은 4

2 기기의 대기 순번은 5

2 기기의 대기 순번은 6

2 기기의 대기 순번은 7

static을 활용한 예제2

클래스

package ch08;

 

public class Student {

 

int studentNumber;

private static int Number = 1;

 

public Student(int studentNumber) {

this.studentNumber = studentNumber;

}

 

public void studentNumber() {

System.out.println(studentNumber + "의 번호는 " + Number);

Number++;

}

 

}

객체

package ch08;

 

public class StudentMainTest {

 

public static void main(String[] args) {

Student student1 = new Student(20163159);

Student student2 = new Student(20163171);

 

student1.studentNumber();

student1.studentNumber();

student1.studentNumber();

 

student2.studentNumber();

student2.studentNumber();

student2.studentNumber();

student2.studentNumber();

 

}

 

}

결과

20163159의 번호는 1

20163159의 번호는 2

20163159의 번호는 3

20163171의 번호는 4

20163171의 번호는 5

20163171의 번호는 6

20163171의 번호는 7

static3

클래스

public class Calculator {

 

// 멤버 변수

int sum = 0;

 

// 두 정수를 더하는 static 메서드 만들기

public static int add(int a, int b) {

// 멤버 변수를 활용할 수 없는 이유는 뭘까?

// sum = a + b;

return a + b;

}

 

// 두 정수를 빼는 메서드

public static int subtract(int a, int b) {

return a - b;

}

 

// 두 정수를 곱하는 메서드

public static int multiply(int a, int b) {

return a * b;

}

 

// 두 정수를 나누는 메서드

public static int divide(int a, int b) {

if(b == 0) {

System.out.println("Error : Division by zero is not allowed");

return 0;

}

return a / b;

}

// 잠시 자리를 빌려서 static 함수를 작성할 수 있다.

public static void main(String[] args) {

// 과제 Calculator를 인스턴스화 시키지 말고

// 동작들을 실행시켜서 확인해 보세요

// System.out.println(add(4, 2));

// System.out.println(subtract(4, 2));

// System.out.println(multiply(4, 2));

// System.out.println(divide(4, 2));

}

}

객체

public class CalculatorMainTest {

 

public static void main(String[] args) {

 

// Calculator에 더하느 기능을 호출해서 결과를 확인하세요

// 단 Calculator를 인스턴스화 시키지 마세요

// static 를 활용할 때 클래스이름.xxx 를 사용할 수 있다.

int result1 = Calculator.add(1, 10);

System.out.println(result1);

int result2 = Calculator.divide(10, 0);

System.out.println(result2);

 

// 인스턴스화

// Calculator a = new Calculator();

// System.out.println(a.add(4, 2));

// System.out.println(a.subtract(4, 2));

// System.out.println(a.multiply(4, 2));

// System.out.println(a.divide(4, 2));

}

 

}

결과

11

Error : Division by zero is not allowed

0

static3

alt + shift + s 생성자 자동생성

getter setter, using field

public class Employee {

 

//잠시 공간을 빌려서 코드를 작성한다

 

private static int serialNum = 1000;

 

private int employeeId;

private String employeeName;

private String department;

 

public Employee(String employeeName) {

this.employeeName = employeeName;

this.employeeId = serialNum;

serialNum++;

}

 

public int getEmployeeId() {

return employeeId;

}

public void setEmployeeId(int employeeId) {

this.employeeId = employeeId;

}

public String getEmployeeName() {

return employeeName;

}

public void setEmployeeName(String employeeName) {

this.employeeName = employeeName;

}

public String getDepartment() {

return department;

}

public void setDepartment(String department) {

this.department = department;

}

 

// serialNum 상태값을 반환하는 기능을 만들어 보자.

public static int getSerialNum() {

// 고민 ! - 객체 메모리에 올라간 상태

// serialNum++;

// static 메서드 안에서는 멤버변수를 사용할 수 없다

// department = "개발부서";

return serialNum;

}

 

// 1. 멤버 변수

// 2. 지역 변수

// 3. static 변수

// 결론 : 어느 메모리 위치에 있느냐에 따라 이름을 구분지어

// 말할 수 있다

 

 

}

 

public class EmployeeMainTest {

 

public static void main(String[] args) {

 

// static은 먼저 메모리에 올라가는 녀석이다.

// 클래스 이름으로 접근할 수 있다.

// int number = Employee.serialNum;

// System.out.println(number);

 

// 만약 객체가 생성되기 전에 serialNum 값을 알고 싶다면

System.out.println(Employee.getSerialNum());

 

Employee employeeKim = new Employee("김길동");

Employee employeeLee = new Employee("이순신");

Employee employee티모 = new Employee("티모");

 

System.out.println(employeeKim.getEmployeeId());

System.out.println(employeeLee.getEmployeeId());

System.out.println(employee티모.getEmployeeId());

 

// serialNum이 public이면 외부에서 static 변수에 접근해서 값을 변경할 수 있는 상태이다.

// Employee.serialNum = 100;

 

}

 

}

결과

1000

1000

1001

1002

싱글톤 패턴이란?



● 프로그램에서 인스턴스가 단 한 개만 생성되어야 하는 경우 사용하는 디자인 패턴
● static 변수, 메서드를 활용하여 구현 할 수 있음

 

싱글톤 패턴으로 회사 객체 구현하기

1. 생성자는 private으로 선언
2. 클래스 내부에 유일한 private 인스턴스(객체) 생성
3. 외부에서 유일한 인스턴스를 참조할 수 있는 public 메서드 제공

 

싱글톤 예제

객체

public class Company {

 

// 싱글톤 패턴으로 설계 하는 방법

// heap 메모리에 오직 객체가 하나만 존재해야 될 경우 사용 가능 하다.

 

// 1. 생성자는 private로 선언해야 한다.

private Company() {}

 

// 2. 클래스 내부에 유일한 private 인스턴스 객체를 생성

private static Company instance = new Company(); // 선언과 동시에 초기화

 

// 3. 외부에서 유일한 instance 변수에 접근할 수 있는 메서드를 제공해야 한다.

public static Company getinstance() {

if (instance == null) {

instance = new Company();

}

return instance;

}

}

클래스

public class CompanyMainTest {

 

public static void main(String[] args) {

// 1.

// 생성자를 private로 선언했기 때문에

// 기본 생성자로 호출할 수 없다

// Company company = new Company();

 

// 2.

// Company.instance 접근 제어 지시자가 private다

 

// 3

// 외부에서 유일하게 Company 객체 주소값에 접근할 수있는 메서드

Company naver = Company.getinstance();

Company tenco = Company.getinstance();

System.out.println(naver);

System.out.println(tenco);

Company mata = Company.getinstance();

System.out.println(mata);

}

 

}

결과

ch08.Company@7c30a502

ch08.Company@7c30a502

ch08.Company@7c30a502

주의사항

※ static 변수는 인스턴스 변수가 아니므로 클래스 이름으로 직접 참조
▶ System.out.println(Employee.serialNum);