본문 바로가기
자바(Java)/자바 클래스

[Java Class.05] Singleton & Final(싱글톤&파이널)

by 긱펀 2024. 2. 23.
반응형

[Java Class.05] Singleton & final

 

1.싱글톤(Singleton)

  • 싱글톤(Singleton): 하나의 객체만 생성하게 만드는 것.
  • new 연산자로 생성자를 호출한 만큼 객체가 생성되기 때문에, 단 하나의 객체만 생성하도록 하려면, 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 한다.
  • 생성자를 외부에서 호출할 수 없도록 하려면 생성자 앞에 private 접근 제한자를 추가해 주면 된다.
// 싱글톤(Singleton) 방식의 클래스 예제 코드
public class Book {
  // 단 하나의 객체 생성
  private static Book singleton_book = new Book();

  private Book() { } // 생성자(private은 다른 클래스에서 접근X)

  static Book getInstance() { // 만들어진 객체 리턴
    return singleton_book;
  }
}

 

// 싱글톤 객체(Singleton object)
public class Main {
  public static void main(String[] args) {
    // Book b1 = new Book(); => error, because of singleton
    Book b2 = Book.getInstance();
    Book b3 = Book.getInstance();

    if(b2 == b3) System.out.println("Same object by singleton.");
    else System.out.println("Different obeject.");
  }
}

 

 

2.final 필드

  • final 필드: 필드에 초기값이 저장되면, 이 값이 최종(final)적인 값이 되어서 프로그램 실행 도중에 수정할 수 없다는 것(수정 시도시 에러 발생)
  • final 필드의 초기값을 주는 방법은, (1) 필드 선언 시에 주거나, (2) 생성자에서 준다.
  • 객체 생성시 초기화 되지 않은 final 필드를 그대로 남겨두면 컴파일 에러가 발생하므로, 생성자에서 final 필드의 최종 초기화를 완료해야 한다.
public class Person {
  final String nationality = "Korea"; // 국적(final 필드)
  final String nationalID;        // 주민번호(final 필드)
  String name;    // 이름

  public Person(String nationalID, String name) {
    // 생성자 안에서 final 변수를 초기화
    this.nationalID = nationalID;
    this.name = name;
  }
}

 

// final 필드 테스트
public class Main {
  public static void main(String[] args) {
    Person p1 = new Person("123456-1234567", "홍길동");

    System.out.println(p1.nationality);
    System.out.println(p1.nationalID);
    System.out.println(p1.name);

    // p1.nationality = "USA"; => error because of final field
    // p1.nationalID = "987654-987654"; => error because of final field
    p1.name = "김길동"; // OK because of non-final field
  }
}

 

  • 위 코드에서 보듯이, final 필드값이 초기화 된 이후에는 수정될 수 없다.

 

 

3.상수(constant)

  • 처음부터 변하면 안되는 값인 "상수"를 필드에 저장할 때는 static final 을 필드앞에 붙입니다.
  • 수학에서 사용되는 원주율 파이나 지구의 무게 등의 상수값을 표현할 때 static final 을 사용합니다.
  • 상수의 이름은 모두 대문자로 쓰는게 관례입니다.
static final double PI = 3.14;
static final int EARTH_RADIUS = 6400;

 

4.final 과 static final의 차이점

  • final 필드가 한 번 초기화 되면 수정할 수 없으니 "상수"라고 생각할 수 있겠지만, 그렇지 않습니다.
  • final필드는 객체마다 저장되고, 생성자의 매개값을 통해서 여러 가지 값을 가질 수 있기 때문에 "상수"가 될수 없습니다.
  • static final 필드는 객체마다 존재하지 않고 클래스에만 존재하므로, 한 번 초기값이 저장되면 변경될 수 없어 "상수"라고 부릅니다.
  • 따라서, 자바에서 상수는 static이면서 final이어야 한다.
public class Earth {
  static final int EARTH_RADIUS = 6371;
  static final double EARTH_SURFACE_AREA;

  static {  // static block
    EARTH_SURFACE_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
    // Math.PI는 원주율을 반환한다.(자바의 기본제공 함수)
  }
}

 

// 상수(static final) 사용 테스트
public class Main {
  public static void main(String[] args) {
    System.out.println(Earth.EARTH_RADIUS + "km");
    System.out.println(Earth.EARTH_SURFACE_AREA + "km^2");
  }
}

 

  • static final(상수)의 초기값이 단순하다면 선언 시에 주는 것이 일반적이다.
  • 만약 초기값이 복잡하다면 static block을 사용해 초기값을 줄 수도 있다.

 

 


 

 

728x90
반응형

댓글