Java Category/Java

[JAVA] 싱글톤(Singleton), final 필드와 상수

ReBugs 2023. 1. 4.

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


싱글톤

프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다.

단 하나만 생성된다고 해서 이 객체를 싱글톤이라고 한다.

 

싱글톤을 만들려면 클래스 외부에서 new 연산자로 생성자 호출을 막아야 한다.

생성자를 외부에서 호출할 수 없도록 하려면 private 접근 제한자를 붙여주면 된다.

생성자를 private으로 접근을 제한했더라도, 클래스 내부에서는 생성자 호출이 가능하다.

 

싱글톤을 만드는 방법은 다음과 같다.

  1. 정적 필드로 자신 타입의 객체를 생성하고 private로 외부 접근을 제한한다.
  2. 생성자를 private를 이용하여 외부 접근을 제한한다.
  3. 정적 메소드를 선언하고 정적 필드에서 참조하고 있는 자신의 객체를 리턴해준다.
package TestPakage;
public class Single {
	//정적 필드
	private static Single obj = new Single();
	
	//생성자
	private Single() {
		
	}
	
	//정적 메소드
	static Single getInstance() {
		return obj;
	}
}

 

위 코드 처럼 싱글톤 객체를 만들면, 외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 방법이다.

 

package TestPakage;
public class Test {
	public static void main(String[] args) {	
		Singleton obj1 = new Singleton();  //컴파일 에러
		Singleton obj2 = new Singleton();  //컴파일 에러
		
		Single a = Single.getInstance();
		Single b = Single.getInstance();
		
		if(a == b) {
			System.out.println("동일 객체");
		} else {
			System.out.println("다른 객체");
		}
	}
}
/*
동일 객체
*/

 

final 필드와 상수

final 필드

final 필드는 초기값이 저장되면 최종적인 값이 되어서 프로그램 실행 도중에 수정할 수 없다.

final 필드의 초기값을 줄 수 있는 방법은 두 가지 이다.

  • 필드 선언 시에 주는 방법
  • 생성자에서 주는 방법

생성자에서 초기값을 주는 경우에, 생성자는 final 필드의 최종 초기화를 마쳐야 하는데 만약 초기화되지 않은 final 필드를 그대로 남겨두면 컴파일 에러가 발생한다.

 

Person.java

package TestPakage;
public class Person {
	final String nation = "Korea";
	final String ssn;
	String name;
	
	public Person(String ssn, String name) {
		this.ssn = ssn;
		this.name = name;
	}
}

 

Test.java

package TestPakage;
public class Test {
	public static void main(String[] args) {	
		Person p1 = new Person("123456-1234567", "홍길동");
		
		System.out.println(p1.nation);
		System.out.println(p1.ssn);
		System.out.println(p1.name);
		
		p1.nation = "ReBugs"; //컴파일 오류, final 필드는 수정 불가능
		p1.ssn = "654321-7654321"; //컴파일 오류, final 필드는 수정 불가능
		p1.name = "아무 이름"; //일반 변수는 수정 가능
	}
}
/*
Korea
123456-1234567
홍길동
*/

 

상수

불변의 값을 상수(static final)라고 부른다.

final 필드는 한 번 초기화되면 수정할 수 없는 필드라고 했다. 그렇다면 final 필드를 상수라고 불러도 되지 않을까?
final 필드를 상수라고 부르진 않는다. 왜냐하면 불변의 값은 객체마다 저장할 필요가 없는 공용성을 띠고 있으며, 여러 가지 값으로 초기화될 수 없기 때문이다.
final 필드는 객체마다 저장되고, 생성자의 매개값을 통해서 여러 가지 값을 가질 수 있기 때문에 상수가 될 수 없다.

상수는 static이면서 final이어야 한다. static final 필드는 객체마다 존재하지 않고 클래스에만 존재한다. 그리고 한 번 초기값이 저장되면 변경할 수 없다.

상수의 초기값을 줄 수 있는 방법은 두 가지 이다.

  • 필드 선언 시에 주는 방법
  • 정적 블록에서 주는 방법

상수 이름은 모두 대문자로 작성하는 것이 관례이고, 만약 서로 다른 단어가 혼합된 이름이라면 언더바(_)로 단어들을 연결한다.

 

Earth.java

package TestPakage;
public class Earth {
	static final double EARTH_RADIUS = 6400;
	static final double EARTH_AREA;
    
    static{
    	EARTH_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
    }
}

Test.java

package TestPakage;
public class Test {
	public static void main(String[] args) {	
		System.out.println("지구 반지름 : " + Earth.EARTH_RADIUS + " km");
		System.out.println("지구 표면적 : " + Earth.EARTH_AREA + "  km^2");	
	}
}
/*
지구 반지름 : 6400.0 km
지구 표면적 : 5.147185403641517E8  km^2
*/

 

'Java Category > Java' 카테고리의 다른 글

[JAVA] 접근 제한자(Access Modifier)  (0) 2023.01.06
[JAVA] 패키지(Package)  (0) 2023.01.05
[JAVA] 인스턴스 멤버와 정적 멤버  (0) 2023.01.03
[JAVA] 메소드(Method)  (0) 2023.01.02
[JAVA] 생성자(Constructor)  (0) 2023.01.01

댓글