이따금 인스턴스 필드들을 모아놓는 일 외에는 아무 목적도 없는 퇴보한 클래스를 작성하려 할 때가 있습니다. class Point { public double x; public double y; } 이런 클래스는 데이터 필드에 직접 접근할 수 있으니 캡슐화의 이점을 제공하지 못합니다. (아이템 15) API를 수정하지 않고는 내부 표현을 바꿀 수 없고, 불변식을 보장할 수 없으며, 외부에서 필드에 접근할 때 부수 작업을 수행할 수도 없습니다. 철저한 객체 지향 프로그래머는 이런 클래스를 상당히 싫어해서 필드들을 모두 private으로 바꾸고 public 접근자(getter)를 추가합니다. class Point { public double x; public double y; public Point(doubl..
어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 바로 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐 차이입니다. 잘 설계된 컴포넌트는 모든 내부 구현을 완벽하게 숨겨, 구현과 API를 깔끔하게 분리합니다. 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식에는 전혀 신경을 쓰지 않습니다. 정보 은닉, 혹은 캡슐화라고 하는 이 개념은 소프트웨어 설계의 근간이 되는 원리입니다. 정보 은닉의 장점 정보 은닉의 장점은 굉장히 많습니다. 그 중 대부분은 시스템을 구성하는 컴포넌트들을 서로 독립시켜서 개발, 테스트, 최적화, 적용, 분석, 수정을 개별적으로 할 수 있게 해주는 것과 연관되어 있습니다. 정보 은닉의 장점은 다음과 같습니다. 시스템 개..
Comparable 인터페이스의 유일무이한 메서드인 compareTo를 알아봅시다. compareTo는 Object의 메서드가 아닙니다. 성격은 두 가지만 빼면 Object의 equals와 같습니다. compareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있으며, 제네릭합니다. Comparable을 구현했다는 것은 그 클래스의 인스턴스들에는 자연적인 순서가 있음을 뜻합니다. 그래서 Comparable을 구현한 객체들의 배열은 다음처럼 손쉽게 정렬할 수 있습니다. Arrays.sort(a); 검색, 극단값, 계산, 자동 정렬되는 컬렉션 관리도 역시 쉽게 할 수 있습니다. 예컨대 다음 프로그램은 명령줄 인수들을 (중복은 제거하고) 알파벳순으로 출력합니다. String이 Comparable을 구현한 ..
Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스(아이템 20)지만, 아쉽게도 의도한 목적을 제대로 이루지 못했습니다. 가장 큰 문제는 clone 메서드가 선언된 곳이 Cloneable이 아닌 Object이고, 그마저도 protected라는 데 있습니다. 그래서 Cloneable을 구현하는 것만으로는 외부 객체에서 clone 메서드를 호출할 수 없습니다. 리플렉션(아이템 65)을 사용하면 가능하지만, 100% 성공하는 것도 아닙니다. 해당 객체가 접근이 허용된 clone 메서드를 제공한다는 보장이 없기 때문입니다. 하지만 이를 포함한 여러 문제점에도 불구하고 Cloneable 방식은 잘 동작하게끔 해주는 구현 방법과 언제 그렇게 해야 하는지를 알려주고, 가능한 다른 선택지에 ..
Object의 기본 toString 메서드가 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없습니다. 이 메서드는 PhoneNumber@adbbd처럼 단순히 클래스_이름@16진수로_표시한_해시코드를 반환할 뿐입니다. toString의 일반 규약에 따르면 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보'를 반환해야 합니다. PhoneNumber@adbbd는 간결하고 읽기 쉽다고 볼 수도 있지만, 707-867-5309처럼 전화번호를 직접 알려주는 형태가 훨씬 유익한 정보를 담고 있습니다. 또한 toString의 규약은 "모든 하위 클래스에서 이 메서드를 재정의하라'고 합니다. equals와 hashCode 규약(아이템 10, 아이템 11)만큼 대단히 중요하진 않지만, toString을 잘 ..
equals를 재정의한 클래스 모두에서 hashCode도 재정의해야 합니다. 그렇지 않으면 hashCode 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것입니다. 다음은 Object 명세에서 발췌한 규약입니다. equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다. equals(Object)가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다. equals(Object)가 두 객체를 다르다고 판단했더라..
equals 메서드는 재정의하기 쉬워 보이지만 곳곳에 함정이 도사리고 있어서 자칫하면 끔찍한 결과를 초래합니다. 문제를 회피하는 가장 쉬운 길은 아예 재정의하지 않는 것입니다. 그냥 두면 그 클래스의 인스턴스는 오직 자기 자신과만 같게 됩니다. 그러니 다음에서 소개하는 상황 중 하나라도 해당한다면 재정의하지 않는 것이 최선입니다. 각 인스턴스가 본질적으로 고유하다 값을 표현하는 게 아니라 동작하는 개체를 표현하는 클래스가 여기 해당합니다. Thread가 좋은 예로, Object의 equals 메서드는 이러한 클래스에 딱 맞게 구현되었습니다. 인스턴스의 '논리적 동치성'을 검사할 일이 없다 예컨대 java.util.regex.Pattern은 equals를 재정의해서 두 Pattern의 인스턴스가 같은 정규..
자바 라이브러리에는 close 메서드를 호출하여 직접 닫아줘야 하는 자원이 많습니다. InputStream, OutputStream, java.sql.Connection 등이 예로 있습니다. 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 합니다. 이런 자원 중 상당수가 안전망으로 finalizer를 사용하고 있지만 finalizer는 그리 믿을만하지 못합니다.(아이템 8) 전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였습니다. 예외가 발생하거나 메서드에서 반환되는 경우를 포함해서 말입니다. static String firstLineOfFile(String path) throws IOException { BufferReader br = new ..
- Total
- Today
- Yesterday
- AWS
- 알고리즘
- node.js
- 객체지향
- Algorithm
- BOJ
- kkoon9
- JPA
- 백준
- Spring Boot
- kotest
- 이펙티브 자바
- BAEKJOON
- 정규표현식
- Olympiad
- 테라폼
- 프로그래머스
- 클린 코드
- 코테
- Java
- Effective Java
- C++
- MSA
- 디자인패턴
- Kotlin
- programmers
- 클린 아키텍처
- 디자인 패턴
- Spring
- 이팩티브 자바
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |