티스토리 뷰
4. 객체 생성을 막을 때는 private 생성자를 사용하라
정적 메소드나 필드를 모아놓고 사용하는 유틸리티 클래스의 경우는 객체를 만들 목적의 클래스가 아니다
- 대표적으로 java.lang.Math, java.util.Arrays, java.util.Collections
객체를 만들 생각이 없다고 생성자를 만들지 않으면.. 객체 생성을 막을 수 있는 것이 아니라 디폴트 생성자가 만들어진다.
* 디폴트 생성자: 객체가 생성될 때 사용자가 초깃값을 명시하지 않으면 컴파일러가 자동으로 생성해주는 생성자
- NoArgsConstructor와 같음
클래스를 abstract로 추상 클래스로 만든다고 해도 소용없다.
-> 하위 클래스를 정의하면 객체 생성이 가능해지기 때문.
그럼 어떻게?
=> private 생성자를 만들어서 외부에서 객체 생성을 못하게 막아버리자
private 생성자를 가지고 있으므로 하위 클래스 상속도 불가능하고, 외부에서 호출도 불가능하다.
<모범 사례 - java.lang.Math class >
public final class Math {
private Math() {}
public static final double E = 2.7182818284590452354;
...
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
....
}
- final class이기 때문에 상속 불가
- private 생성자로 외부에서 생성 불가
- static 변수/메소드로 클래스 레벨에서 공유되어 사용
(+) final 키워드에 대해..
final 키워드는 값을 한번 할당한 이후에는 변경 불가능(immutable)함을 뜻한다.
final 클래스: 상속할 수 없는 클래스
final 메서드: 오버라이딩 불가능한 메소드
final 변수: 수정 불가능한 변수. static final 조합으로 상수로 많이 쓰임
"불변함" 이라는 것의 이점이 상당히 많다!
* final 변수는 변수 선언 시에 or 생성자를 통해서만 할당해줄 수 있다.
* final 클래스라도 내부 변수가 final이 아니라면 setter 등을 통해서 값을 변경해줄 수 있다.
(++) 익명 클래스 or 람다식 내부에서 참조하는 외부 지역변수는 final 변수 or Effectively final 변수만 가능하다
- effectively final이란 Java 8에서부터 등장한 기능으로, final이 없어도 따로 변경이 없다면 final 변수로 간주해주는 기능
(객체의 경우에는 참조값만 바뀌지 않으면 된다)
- 익명 클래스나 람다식의 경우에는 멀티 스레드 환경에서 동작할 수 있기에, 메소드 종료 시점보다 더 늦게 실행될 가능성이 존재한다. 이 경우, 스택 영역에 저장되어있던 지역변수들이 메소드가 다 종료되면서 사라져 버리기에 람다식이 참조할 값이 없어져버림.
- 인스턴스 변수는 힙 영역에, 클래스 변수(static)는 메서드 영역에 저장되므로 final이 아니라도 접근 가능함.
public void method() {
int val = 0;
new Thread(() -> {
try {
Thread.sleep(90000);
System.out.println(val);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
(위와 같은 상황을 방지하기 위함)
(+++) Java의 메모리 구조에 대해..
1. Method (= Class)
- 클래스, 인터페이스, 메소드, 클래스 변수(static) 정보가 저장되는 영역.
- 모든 스레드가 공유하여 사용
2. Heap
- new를 통해 생성된 인스턴스 객체(인스턴스 변수(전역변수) 포함)들이 저장되는 영역.
- GC에 의해 회수되기 전까지는 사용되지 않아도 남아있음
- 모든 스레드가 공유하여 사용
3. Stack
- 메소드 내에서 사용되는 지역변수, 매개변수, 리턴값이 저장되는 영역.
- 메소드가 호출될 때 생성되고, 메소드가 종료되면 바로 사라짐
- 각 스레드마다 별개로 존재
4. PC Register: 현재 수행중인 JVM 명령어 주소 저장
5. Native Method Stack: 자바 외 다른 언어의 동작을 위해 할당된 영역
'JAVA' 카테고리의 다른 글
더 이상 사용되지 않는 객체는 제때 처리하자 (0) | 2022.07.17 |
---|---|
불필요한 객체를 만들지 말자 (0) | 2022.07.17 |
싱글톤은 Enum 타입으로 만들어라 (0) | 2022.07.15 |
생성자 인자가 많을때는 빌더 패턴 (0) | 2022.07.15 |
생성자 대신 정적 팩토리 메서드 (0) | 2022.07.15 |