본문 바로가기
프로그래밍 언어/java

[java] static 변수와 메서드, 싱글톤 패턴

by m2162003 2021. 2. 26.

static 변수

= 클래스 변수, 정적 변수

여러 인스턴스가 하나의 값을 공유하기 위해 만들어졌다. c/c++의 전역변수와 동일하다.

 

static 변수는 처음 프로그램이 로드될 때 데이터 영역에 한번만 생성된다.

인스턴스의 생성과 상관없이 사용할 수 있으므로 인스턴스 이름이 아니라 클래스이름으로 참조한다.

 

Student.serialNum = 100;

 

static변수와 인스턴스 변수

 

스택 메모리에 위치한 참조 변수들은 static 변수 참조 시 데이터 영역의 동일한 메모리를 참조한다.

 

static 메서드

=클래스 메서드, 정적 메서드

static 변수를 위한 기능을 제공하는 메걷이다.

static 메서드에서는 인스턴스 변수를 사용할 수 없다. (일반 메서드에서 static 변수 사용은 당연히 가능하다.)

static 변수와 동일하게 클래스 이름을 참조하여 사용하는 메서드이다.

Student.getSerialNum();

 

변수 유형 정리

 

 

Singleton Pattern

단 하나의 인스턴스를 생성하여 그 인스턴스를 계속 사용하는 것.

어플리케이션이 시작될 때 어떤 클래스가 최초 한번만 메모리를 할당하여,

생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 생성 이후에 호출된 생성자는 최소의 생성한 객체를 반환한다.

 

사용이유

고정된 메모리 영역을 사용하기 때문에 메모리 낭비를 방지할 수 있다.

싱글톤으로 만들어진 클래스 인스턴스는 전역 인스턴스이기 때문에 다른 클래스 인스턴스들이 데이터를 공유하기 쉽다.

 

자바에서 사용하는 법:

최초 한번만 메모리를 할당하기 위해 static으로 선언하고

생성자를 private으로 선언하여 재생성이 불가능하게 만든 후 getInstance()로 받아쓸 수 있다.

 

public class Company {
	private static Company instance = new Company();
	
	private Company() {}
	
	//외부에서 호출 시 동일한 메서드 호출을 위해 static 사용
	public static Company getInsance() {
		
		if(instance == null) {
			instance = new Company();
		}
		return instance;
	}

}

 

import java.util.Calendar;
public class CompanyTest {
	
	public static void main(String[] args) {
		Company com1 = Company.getInsance();
		Company com2 = Company.getInsance();
		
		System.out.println(com1);
		System.out.println(com2);
		
		Calendar calendar = Calendar.getInstance();
        //자바 util 사용
		//new Calendar 불가능, 유일한 객체를 가져오기 때문
		
	}
}

 

출력하면 동일한 주소값이 확인된다.

 

static 변수 응용

static을 사용해서 DB의 auto increment 기능을 구현해보자.

package staticex;

public class Student {
	private static int serialNum = 1000;
		
	public static int getSerialNum() {
		return serialNum;
	}
	public static void setSerialNum(int serialNum) {
		Student.serialNum = serialNum;
	}
}

serialNum을 private static으로 선언해서 전역변수 역할을 하게끔 만들었다.

해당 변수는 private이기 때문에 get/set 없이는 접근이 불가능하다.

그리고 static이기 때문에 인스턴스가 아닌 클래스 자체로 접근한다.

 

Student 객체가 생성될 때마다 자동으로 serialNum이 증가하게 만들어보자.

package staticex;

public class Student {
	private static int serialNum = 1000;
	private int studentId;
	public String name;
	
	public Student(String name) {
		this.name = name;
		serialNum++;
		studentId = serialNum;
	}
	
	public int getStudentId() {
		return this.studentId;
	}
	
	public static int getSerialNum() {
		return serialNum;
	}
	public static void setSerialNum(int serialNum) {
		Student.serialNum = serialNum;
	}
}
package staticex;
public class StudentIDTest {
	public static void main(String[] args) {
		System.out.println(Student.getSerialNum());
        //System.out.println(lee.serialNum); 참조 변수가 아닌 클래스로 access
		
        Student lee = new Student("lee");
		Student kim = new Student("kim");
        
		System.out.println(lee.getStudentId());
		System.out.println(kim.getStudentId());
		
	}
}

 

출력값을 확인해보면 기존 serialNum 1000에서 인스턴스가 생성될때마다 1씩 증가한 것을 확인할 수 있다.

 

Singleton 패턴 응용

 

유일한 카드 회사 객체를 선언하고 이 회사에서 카드를 발급하면 항상 고유번호가 자동으로 생성된다.

10001부터 시작하여 카드가 생성될 때마다 10002, 10003이 되도록 만들자.

 

먼저 카드 회사를 싱글톤으로 선언한다.

싱글톤으로 만들기 위해 private static으로 선언한다.

package staticex.quiz;

public class CardCompany {
	private static CardCompany instance = new CardCompany();
	
	public static CardCompany getInstance() {
		
		if(instance == null) {
			instance = new CardCompany();
		}
		return instance;
	}
	
	public Card createCard() {
		return new Card();
		
	}
}

 

이 회사에서 createCard()를 할 때마다 고유 번호가 발급되어야 한다.

autoIncrement를 전역변수로 두고 Card 생성자에서 cardNum이 AI를 받도록 만든다.

package staticex.quiz;

public class Card {
	private static int autoIncrement = 10001;
	private int cardNumber;
	
	public Card() {
		this.cardNumber = Card.autoIncrement;
		Card.autoIncrement++;
	}
	
	public int getCardNumber() {
		return this.cardNumber;
	}
}

 

메인에서 확인가능하다.

package staticex.quiz;

public class CardCompanyTest {
	public static void main(String[] args) {
		CardCompany com = CardCompany.getInstance();
		
		Card myCard = com.createCard();
		Card yourCard = com.createCard();
		
		System.out.println(myCard.getCardNumber());
		System.out.println(yourCard.getCardNumber());
	}
}

'프로그래밍 언어 > java' 카테고리의 다른 글

[java] 업캐스팅, 타운캐스팅  (0) 2021.03.10
[java] 상속, 생성과정  (0) 2021.03.09
[java] this와 참조자료형  (0) 2021.02.24
[java] 접근 제어자, 정보 은닉  (0) 2021.02.24
[java] 클래스 생성자  (0) 2021.02.24

댓글