| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- AWS
- 오블완
- UNICON
- CICD
- 프롬프트엔지니어링
- 프로그래밍
- Redis
- 게임개발동아리
- 인프라
- NAT gateway
- 전국대학생게임개발동아리연합회
- Route53
- 스프링부트
- 백엔드개발자
- 프리티어
- 티스토리챌린지
- 42서울
- Spring boot
- UNIDEV
- UNICON2023
- 체크인미팅
- bastion host
- 생활코딩
- EC2
- openAI API
- spring ai
- 도커
- 개발공부
- 캡스톤디자인프로젝트
- 라피신
- Today
- Total
Hyun's Wonderwall
[Java] 이펙티브 자바 - 1장, 2장(아이템 1~9) 본문
자바와 더욱 친해지고 싶어 이펙티브 자바 3판을 읽기 시작했습니다. 책을 읽으며 배운 내용, 관련해 경험했던 사례, 추가로 찾아본 점 등을 작성합니다.
1장
📎📎📎
이 책은 자바 11 버전에 기반한다. 최신 자바 LTS 버전은 21이기에 자바 11 이후 주요 업데이트 사항을 따로 찾아보고 인상적인 것들을 메모했다.
Java SE 12: switch문 확장 ('->' 함수형 방식), switch문 값 리턴 가능
Java SE 13: switch에서 yield 키워드로 break value;처럼 사용 가능
Java SE 14: instanceof 패턴 매칭, record 타입 지원
Java SE 15: sealed(클래스 봉인), 다중 텍스트 블록(""" 방식)
Java SE 16: Vector API 인큐베이터
Java SE 17 (LTS)
Java SE 18: try-finally 권장X, try-with-resources 권장
Java SE 19: 가상 스레드 프리뷰
Java SE 21 (LTS): 템플릿 문자열(https://openjdk.org/jeps/430), 레코드 패턴(https://openjdk.org/jeps/440), switch 문 패턴 매칭 정식 출시, 가상 스레드(Virtual Threads) 정식 출시 등
현재 Java 버전은 24까지 출시되었다. 나는 Java 21을 주로 사용하는데, 최근 프로젝트에서 템플릿 문자열 방식을 유용하게 사용했다.
📎📎📎
용어 관련 서론
- 자바가 지원하는 자료형 4가지: 인터페이스(interface), 클래스(class), 배열(array), 기본 타입(primitive)
- 애너테이션(Annotation)은 인터페이스의 일종 (-> 애너테이션의 정의를 보면 public @interface 인터페이스이름() )
- 열거 타입(Enum)은 클래스의 일종
- 인터페이스, 클래스, 배열은 참조 타입(reference type), 즉 객체.
- 클래스의 멤버: 필드, 메서드, 멤버 클래스, 멤버 인터페이스
- 메서드 시그니처: 메서드 이름, 입력 매개변수 타입들 (-> 메소드 오버로딩과 관련)
- 상속(inheritance) = 서브클래싱(subclassing)
- 인터페이스 상속 관련 2방법: 클래스가 인터페이스를 구현(implement), 인터페이스가 다른 인터페이스를 확장(extend)
- 접근 수준(access level): public, protected, private, package-private(=default, 아무것도 붙이지 않은)
- 공개 API(exported API): 프로그래머가 클래스, 인터페이스, 패키지를 통해 접근할 수 있는 모든 클래스, 인터페이스, 생성자, 멤버, 직렬화된 형태(serialized form).
- API의 사용자: API를 사용하는 프로그램 작성자
- API의 클라이언트(client): API를 사용하는 클래스(코드)
- API 요소(element): 클래스, 인터페이스, 생성자, 멤버, 직렬화된 형태 총칭. 공개 API는 그 API를 정의한 패키지의 밖에서 접근할 수 있는 API 요소로 이루어짐. 모든 클라이언트가 접근할 수 있고 API 작성자가 지원하기로 약속한 API 요소들. Javadoc 유틸리티 실행->API 문서 생성됨 (패키지의 공개 API: 그 패키지의 모든 public 클래스와 인터페이스의 public 혹은 protected 멤버와 생성자로 구성됨)
- Java9의 모듈 시스템 -> 공개할 패키지 선택 가능하게 됨
2장
아이템 1. 생성자 대신 정적 팩터리 메서드를 고려하라
client가 클래스의 인스턴스 얻는 방법: public 생성자 or 정적 팩터리 메서드(static factory method)
정적 팩터리 메서드 장점
1. 이름 가짐: 반환될 객체 직관적 설명 가능
2. 호출될 때마다 인스턴스 새로 생성하지는 않아도 됨: 인스턴스 미리 만들어놓거나 새로 생성된 인스턴스 캐싱하여 재활용 가능.
- ex: Boolean.valueOf(boolean)은 아예 인스턴스 생성하지 않음(Booelan.TRUE/Boolean.FALSE enum을 반환함). Flyweight pattern.
- 인스턴스 통제 클래스
- 왜 인스턴스 통제? (1) 클래스를 싱글톤(singleton)으로. (2) 클래스를 인스턴스화 불가하게끔. (3) 불변값 클래스에서 동치인 인스턴스가 단 하나뿐임을 보장.
- 열거 타입: 인스턴스가 하나만 만들어짐을 보장함
3. 반환 타입의 하위 타입 객체를 반환 가능 -> 반환할 객체의 클래스 선택 가능하게 가능
- API 만들 때 이를 이용하면 구현 클래스 공개하지 않고도 객체 반환 가능. API 작게 유지 가능
- 인터페이스대로 동작하는 객체를 얻을 것임을 알기에 실제 구현 클래스 찾아보지 않아도 됨(-> 추상화 이점)
- Java 8부터 인터페이스에 정적 메서드 선언 가능 (->인스턴스와 불가 동반 클래스 만들 필요 x) public static 멤버들을 인터페이스에 두고 사용함 (정적 메서드만 private 허락함)
4. 입력 매개변수에 따라 매번 다른 클래스의 객체 반환 가능
5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 됨
- 서비스 제공자 프레임워크: JDBC 등. 구현체들을 클라이언트에 제공하는 역할을 통제. 클라이언트를 구현체로부터 분리.
- 서비스 인터페이스, 제공자 등록 API, 서비스 접근 API. (+종종 서비스 제공자 인터페이스 쓰이기도. 이가 없다면 각 구현체를 인스턴스로 만들 때 리플렉션을 사용해야.)
- 클라이언트: 서비스 접근 API 사용 시 원하는 구현체의 조건을 명시 가능. -> 유연한 정적 팩터리
- 변형예시) 브리지 패턴: 공급자가 제공하는 것보다 더 풍부한 서비스 인터페이스를 클라이언트에 반환.
- 예시) 의존성 주입(DI) 프레임워크
- ServiceLoader: 범용 서비스 제공자 프레임워크. 직접 만들 필요 거의 없어짐.
정적 팩터리 메서드 단점
1. 정적 팩터리 메소드만 사용하면 하위 클래스 만들 수 없음 -> (장점) 상속보다 컴포지션 사용하도록 유도.
2. 프로그래머가 찾기 어려움
정적 팩터리 메서드 흔한 명명 방식들
- from
- of
- valueOf
- instance / getInstance
- create / newInstance
- getType
- newType
- type
정적 팩터리 메서드 사용하는 게 유리한 경우가 많다. 사용하자.
아이템 2. 생성자에 매개변수가 많다면 빌더를 고려하라
과거 패턴 1: 점층적 생성자 패턴
- but, 매개변수 많아지면 클라이언트 코드 작성/읽기 어렵
과거 패턴 2: Java Beans 패턴
- 매개변수 없는 생성자로 객체 만든 후 setter 메서드들을 호출해 매개변수 값 설정
- 단점: 객체 하나 만드려면 메서드 여러개 호출해야, 중간과정에서 일관성이 무너진 상태에 놓임. 클래스를 불변으로 만들 수 없음
- 불변 위해 freeze 방법 있지만 사용하지 X
추천 패턴: 빌더 패턴.
- 클라이언트가 필수 매개변수만으로 생성자(or 정적 팩터리) 호출해 빌더 객체 얻고, 일종의 setter들로 원하는 선택 매개변수들을 설정. 마지막으로 build() 호출
- 내부 구조 코드 통해 final o/x 비교
- 계층적으로 설계된 클래스와 함께 사용하자
아이템 3. private 생성자나 열거 타입으로 싱글톤임을 보증하라
원소가 하나뿐인 열거 타입이 싱글톤을 만드는 가장 좋은 방법.
아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라
생성자를 private로 작성해 클래스 인스턴스화 막기.
아이템 5. 의존 객체 주입을 사용하라
인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식.
- 생성자에 자원 팩터리 넘겨주는 방식 가능
- 클라이언트가 제공한 팩터리로 구성된 걸 생성하게끔 한다.
아이템 6. 불필요한 객체 생성을 피하라
불변 객체는 언제든 재사용 가능. 안전함이 명백.
- ex. 동일한 문자열 리터럴을 사용하는 모든 코드가 같은 객체를 재사용.
생성자 대신 정적 팩터리 메서드를 제공하는 불변 클래스에서는 정적 팩터리 메서드를 사용해 불필요한 객체 생성을 피할 수 있다.
- Boolean(String) 생성자 대신 Boolean.valueOf(String) 팩터리 메서드 사용.
생성 비용이 비싼 객체 사용 주의
- String.matches: 정규표현식으로 문자열 형태 확인 메서드는 내부적으로 Pattern 인스턴스를 만든다(곧바로 가비지 컬렉션 대상) -> 인스턴스 생성 비용이 높다.
- 성능 개선: Pattern 인스턴스를 클래스 초기화(정적 초기화) 과정에서 직접 생성해 캐싱해두고, 메서드가 호출시마다 인스턴스를 재사용
+ 어댑터
오토박싱, 박싱과 언박싱
오토박싱: 프로그래머가 기본 타입과 박싱된 기본 타입을 섞어 쓸 때 자동으로 상호 변환해주는 기술. 의도치 않게 오토박싱이 숨어드는 문제 발생 가능.
- ex. 덧셈 연산을 할 때 sum 변수를 Long으로, iterator i를 long으로 선언해 sum += i; 식에서 오토언박싱→연산→오토박싱이 반복.
내부적으로 sum = Long.valueOf(sum.longValue() + i); 와 같다.
불필요한 Long 인스턴스가 매우 많이 생성된다. valueOf는 이러한 구조:
public static Long valueOf(long l) {
if (l >= -128 && l <= 127)
return LongCache.cache[(int)l + 128];
else
return new Long(l);
}
박싱된 기본 타입보다는 기본 타입을 사용
자체 객체 풀을 만드는 것은 비추천. (방어적 복사가 필요한 상황에서 객체 재사용했을 때 피해 > 필요 없는 객체 반복 생성 피해)
아이템 7. 다 쓴 객체 참조를 해제하라
메모리 누수를 가비지 컬렉터가 보지 못하는 경우가 존재한다. (겉으로 잘 드러나지 않아 시스템에 잠복하기도)
- ex. 사용자가 Stack 만든 경우, Stack Pointer 가리키는 밖 영역의 객체가 메모리 계속 점유(누수) -> null로 해제해야.
메모리 누수를 일으키는 주범: 자기 메모리를 직접 관리하는 클래스, 캐시, 리스너 및 콜백 등
아이템 8. finalizer와 cleaner 사용을 피하라
finalizer, cleaner 사용하지 말자. 안전망 역할이나 중요하지 않은 네이티브 자원 회수용으로만 사용하자. 이런 경우라도 불확실성과 성능 저하에 주의해야 한다.
- Native Peer
아이템 9. try-finally보다는 try-with-resources를 사용하라
예외처리 시 꼭 회수해야 하는 자원을 다룰 때는 try-with-resources를 사용하자. (코드 간결성, 명료성 향상)
try-with-resources에서도 catch 절을 쓸 수 있어 try 문을 더 중첩하지 않고도 다수의 예외를 추리할 수 있다.
자바 try-with-resources 기본 포맷 (catch절 포함):
try (자원선언1; 자원선언2; ...) {
// 자원 사용 코드
} catch (예외타입1 e) {
// 예외 처리 코드
} catch (예외타입2 e) {
// 추가 예외 처리
}'Study > Java' 카테고리의 다른 글
| [Java] 이펙티브 자바 - 6장(2/2), 7장(1/2) (아이템 37~45) (2) | 2025.08.16 |
|---|---|
| [Java] 이펙티브 자바 - 5장(2/2), 6장(1/2) (아이템 28~36) (4) | 2025.08.16 |
| [Java] 이펙티브 자바 - 4장(2/2), 5장(1/2) (아이템 19~27) (4) | 2025.08.02 |
| [Java] 이펙티브 자바 - 3장, 4장(1/2) (아이템 10~18) (2) | 2025.07.26 |
| [Java] 생활코딩 Java 입문 수업 강의 메모 (완강) (0) | 2023.02.28 |