일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 이펙티브자바
- 탐욕법
- BFS
- 깊이우선탐색
- 프로그래머스
- Database
- Effective Java
- java
- springboot
- mybatis
- 그리디알고리즘
- SQL
- 너비우선탐색
- 데이터베이스
- Spring
- DP
- 피보나치
- 알고리즘
- 우선순위큐
- select
- join
- 백준
- IntelliJ
- Greedy
- 정렬
- 코테
- DFS
- mariaDB
- 다이나믹프로그래밍
- db
Archives
- Today
- Total
땀두 블로그
[도서] Effective Java - Item 24. 멤버 클래스는 되도록 static으로 만들라 본문
이펙티브 자바 3판을 읽으면서 내용을 정리하는 포스트입니다. 혹시 틀린 부분이나 잘 못 설명한 부분이 있으면 댓글로 남겨주시면 수정하도록 하겠습니다.
Item 24. 멤버 클래스는 되도록 static으로 만들라
중첩 클래스(nested class)
- 다른 클래스 안에 정의된 클래스
- 자신을 감싼 바깥 클래스에서만 쓰여야 한다.
중첩 클래스의 종류
- 정적 멤버 클래스
- (비정적) 멤버 클래스
- 익명 클래스
- 지역 클래스
정적 멤버 클래스
- class 내부에서 static으로 선언된 클래스로 다른 클래스 안에 선언된다.
- 바깥 클래스의 private 멤버에도 접근할 수 있다.
비정적 멤버 클래스
- 바깥 클래스의 인스턴스와 암묵적으로 연결된다.
- 비정적 멤버 클래스의 인스턴스 메소드에서 정규화된 this를 사용해 바깥 인스턴스의 메소드를 호출하거나 참조를 가져올 수 있다.
- 개념상 중첩 클래스의 인스턴스가 바깥 인스턴스와 독립적으로 존재할 수 있다면 정적 멤버 클래스로 만들어야 한다.
- 비정적 멤버 클래스와 바깥 인스턴스 사이의 관계는 멤버 클래스가 인스턴스화될 때 확립되며, 더 이상 변경할 수 없다.
- 어댑터를 정의하는데 자주 쓰인다.
- 어떤 클래스의 인스턴스를 감싸 마치 다른 클래스의 인스턴스처럼 보이게 하는 뷰로 사용한다.
- Map 인터페이스의 구현체는 자신의 컬렉션 뷰를 구현할 때 비정적 멤버 클래스를 사용한다.
- Set과 List같은 다른 컬렉션 인터페이스 구현들도 자신의 반복자를 구현할 때 비정적 멤버 클래스를 주로 사용한다.
멤버 클레스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 static을 붙여서 정적 멤버 클래스로 만들어야 한다.
- static을 생략하여 비정적 멤버 클래스로 생성할 경우 바깥 인스턴스로의 숨은 외부 참조를 갖게 된다.
- 숨은 외부참조는 추가적인 시간과 메모리 공간을 소비한다.
- 가비지 컬렉션이 바깥 클래스의 인스턴스를 수거하지 못하는 메모리 누수가 생길 수 있다.
- 참조가 눈에 보이지 않아 문제의 원인을 찾기 어려워 때로는 심각한 상황을 초래할 수 있다.
private 정적 멤버 클래스는 흔히 바깥 클래스가 표현하는 객체의 구성요소를 나타낼 때 쓴다.
- key-value를 매칭시키는 Map 인스턴스에서 키-값 쌍을 나타내는 엔트리(Entry)는 맵과 연관이 있지만 엔트리의 메소드(getKey, getValue, setValue)은 맵을 직접 사용하지 않는다.
- 엔트리를 비정적 멤버 클래스로 표현하는 것은 낭비고, private 정적 멤버 클래스가 가장 알맞는다.
- 엔트리를 선언할 때 실수로 static을 빠뜨려도 동작하긴 하지만, 모든 엔트리가 바깥 맵으로의 참조를 갖게 되어 공간과 시간을 낭비하게 된다.
- 멤버 클래스가 공개된 클래스의 public이나 protected 멤버라면 정적이냐 아니냐는 더 중요하다.
- 멤버 클래스 역시 공개 API가 되니, 혹시라도 향후 릴리스에서 static을 붙이면 하위 호환성이 깨진다.
익명클래스
이름이 없다.
바깥 클래스의 멤버가 아니다.
쓰이는 시점에 선언과 동시에 인스턴스가 만들어진다.
정적 문맥에서라도 상수 변수 이외의 정적 멤버는 가질 수 없다.
- 상수 표현을 위해 초기화된 final 기본 타입과 문자열 필드만 가질 수 있다.
자바 8 이전에는 즉석에서 작은 함수 객체나 처리 객체를 만드는데 익명 클래스를 사용했지만 이제 람다를 주로 사용한다.
정적 팩터리 메소드를 구현할 때도 익명 클래스를 사용한다.
익명 클래스의 제약 사항
- 선언한 지점에서만 인스턴스를 만들 수 있고, instanceof 검사나 클래스의 이름이 필요한 작업은 수행할 수 없다.
- 익명 클래스를 사용하는 클라이언트는 그 익명 클래스가 상위 타입에서 상속한 멤버 외에는 호출할 수 없다.
- 여러 인터페이스를 구현할 수 없고, 인터페이스를 구현하는 동시에 다른 클래스를 상속할 수도 없다.
- 익명 클래스를 사용하는 클라이언트는 그 익명 클래스가 상위 타입에서 상속한 멤버 외에는 호출할 수 없다.
- 익명 클래스는 표현식이 중간에 등장하므로 짧지 않으면 가독성이 떨어진다.
지역 클래스
- 가장 사용빈도가 적다.
- 지역 변수를 선언할 수 있는 곳이면 실질적으로 어디서든 선언할 수 있고, 유효 범위도 지역 변수와 같다.
- 멤버 클래스처럼 이름이 있고 반복해서 사용할 수 있다.
- 익명 클래스처럼 비정적 문맥에서 사용될 때만 바깥 인스턴스를 참조할 수 있으며, 정적 멤버는 가질 수 없으며 가독성을 위해 짧게 작성해야 한다.
'도서' 카테고리의 다른 글
[도서] Effective Java - Item 25. 톱레벨 클래스는 한 파일에 하나만 담으라 (0) | 2022.05.11 |
---|---|
[도서] Effective Java - Item 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 (0) | 2022.05.11 |
[도서] Effective Java - Item 22. 인터페이스틑 타입을 정의하는 용도로만 사용하라 (0) | 2022.05.11 |
[도서] Effective Java - Item 21. 인터페이스는 구현하는 쪽을 생각해 설계하라 (0) | 2022.05.11 |
[도서] Effective Java - Item20. 추상 클래스보다는 인터페이스를 우선하라 (0) | 2022.05.11 |
Comments