![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/dr4g4k/btqVnXUw43y/1E4CMIVLXQUlmnPdlhacW0/img.png)
내부 데이터와 내부 구현 정보가 외부로부터 잘 숨겨진 컴포넌트는 잘 설계된 컴포넌트라 할 수 있다. 즉, 정보 은닉과 캡슐화가 잘 되어있는 컴포넌트는 잘 설계된 컴포넌트라 볼 수 있다. 잘 설계된 컴포넌트는 다음과 같은 특징을 가지고 있다. 1. 캡슐화가 잘 되어있다. 2. 모든 내부 구현을 완벽히 숨겨, 구현과 노출되는 API가 깔끔하게 분리되어있다. 3. 오직 API로만 다른 컴포넌트와 메시지를 주고받으며, 서로의 내부 동작 방식에 신경 쓰지 않는다. 그만큼 정보 은닉, 캡슐화의 개념은 오늘날 소프트웨어 설계의 근간이되는 중요한 원리이다. 캡슐화의 장점 1. 서로 내부 구현을 신경쓰지 않아도 되기 때문에 컴포넌트를 병렬로 개발할 수 있어 시스템 개발 속도가 빨라진다. (생산성 향상) 2. 잘 분리되어..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/bD0AN4/btqU52RqO6B/by7krm8cEMlSZzuQtbNkkk/img.png)
Comparable을 구현하면 손쉽게 컬렉션을 정렬할 수 있다. Comparable 인터페이스를 활용하는 수많은 제네릭 알고리즘과 컬렉션의 힘을 좁쌀만 한 노력으로 누릴 수 있는 것이다. 따라서 알파벳, 숫자, 연대와 같이 순서가 명확한 클래스를 작성한다면 반드시 Comparable을 구현하자. compareTo 메서드의 일반 규약 compareTo 메서드의 일반 규약은 equals의 규약과 비슷하다. compareTo는 기준 객체와 주어진 객체의 순서를 비교한다. compareTo 반환값의 기준 기준 객체 주어진 객체 → 1 반환 첫 번째 규약 x.compareTo(y) 0..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/bj2sXb/btqUvDcbFbn/EigzxhK49kCPup6OLOGIIk/img.png)
클래스에서 clone을 재정의 하기 위해서는 해당 클래스에 Cloneable 인터페이스를 상속받아 구현한다. 그런데 clone 메서드는 Cloneable 인터페이스가 아닌 Object에 선언되어있다. Cloneable 인터페이스는 아무것도 선언되어있지 않은 빈 인터페이스이다. 메서드 하나 없는 Cloneable 인터페이스는 대체 무슨 일을 할까? Cloneable 인터페이스의 역할 Cloneable 인터페이스는 상속받은 클래스가 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스(mixin interface)이다. mixin interface란? 클래스가 본인의 기능 외에 추가로 구현할 수 있는 자료형으로, 선택적인 기능을 제공한다는 사실을 명시하기 위해 쓰인다. Cloneable 인터페이스는 O..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/5BRp7/btqT7VSFXNx/A48tpvNci1erXL4cqS6wik/img.png)
Object의 기본 toString 메서드가 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없다. Object.toString()은 [클래스이름]@[16진수로 표시한 해시코드]의 형태로 반환될 뿐이다. toString() 일반 규약 1) 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야 한다. 2) 모든 하위 클래스에서 이 toString 메서드를 재정의해야 한다. 실전에서 toString은 객체 내의 중요 정보를 전부 담아 반환하는 것이 좋다. toString을 잘 구현하면 사용하기 편하고 디버깅이 쉬워진다. toString 구현 시 문서화 포맷 명시하는 경우 [장점] 1) 포맷을 명시하면 그 객체는 표준적이고, 명확하고, 사람이 읽을 수 있다. 2) 값 그대로 입출력에 사용하거..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/dYUdFP/btqS4LRk1mG/xTHJsurhhAyXi6ERlhkeV0/img.png)
1. equals를 재정의한 클래스 모두에서 hashCode도 재정의해야 한다. hashCode를 재정의하지 않으면 hashCode 일반 규약을 어기게 되어 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제가 발생한다. hashCode 재정의 조건 equals 비교에 사용되는 정보가 변경되지 않는다면, hashCode는 항상 같은 값을 반환해야 한다. equals가 두 객체가 같다고 판단하면, hashCode는 같은 값을 반환해야 한다. equals가 두 객체가 다르다고 판단해도, hashCode가 꼭 다를 필요는 없다. 다만, 다른 객체에서는 다른 값을 반환해야 성능이 좋아진다. hashCode 재정의를 잘못했을 때 크게 문제가 되는 조항은 2번이다. 논리적으로 같은 객체는 같은 해..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/b8Fb3t/btqSa9kavdt/Mke0oRcWimGL8fthz7WP51/img.png)
equals 메서드는 재정의하기 쉬워 보이지만 곳곳에 함정이 도사리고 있다. 가장 쉬운 길은 아예 재정의하지 않는 것이다. 1. equals를 재정의하지 않아도 되는 경우 1.1 각각의 객체가 본질적으로 고유할 때 값 표현 객체가 아닌 동작하는 개체를 표현하는 클래스일 때를 말한다. 대표적인 예로 Thread, Controller, Service 등이 이 조건에 부합한다. 1.2 인스턴스의 논리적 동치성을 검사할 일이 없을 때 Pattern의 인스턴스가 같은 정규 표현식을 나타내는지 검사하거나 Random 클래스의 equals 메서드가 큰 의미를 가지지 못하는 것처럼 클라이언트가 이 방식이 필요 없다고 판단되면 equals를 재정의 하지 않아도 된다. 1.3 상위 클래스에서 재정의한 equlas가 하위 ..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/ctF2cu/btqRAkfVpgo/wUoFwn6CWp5ljuhv6CajT0/img.png)
자바에는 close 메서드로 직접 닫아줘야 하는 자원이 많다. ex) InputStream, OutputStream, java.sql.Conncetion 등 자원 닫기는 클라이언트가 놓치기 쉬워 예측할 수 없는 성능 문제로 이어지기 때문에 자원을 닫는 수단으로 try-finally가 많이 사용되었다. 1. try-finally의 단점 1.1 코드 가독성이 떨어진다. String firstLineOfFile(String path) throw IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); } } 가독성이 나쁘지않다. 하지만 자원..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/cKFYLC/btqRCWeLeNh/NzsEEcsvF9DaZrXFRT544K/img.png)
자바의 객체와 관련된 자원 회수는 가비지 컬렉터가 담당하고 있다. 따라서 프로그래머에게 객체 자원 수거에 대한 아무런 작업도 요구하지 않지만, 그럼에도 자바는 두 가지 객체 소멸자를 가지고 있다. 비메모리 자원 회수는 try-with-resources와 try-finally를 사용해 해결한다. finalizer 예측할 수 없고, 상황에 따라 위험할 수 있어 보통 불필요하다. cleaner finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고 느리다. 이 역시 보통은 불필요하다. 두 가지의 객체 소멸자는 예측할 수 없다. finalizer와 cleaner는 호출 후 즉시 수행된다는 보장이 없다. 즉, 호출된 후 언제 실행될지 알 수 없다는 의미이다. finalizer와 cleaner가 실행되기까지..
![](http://i1.daumcdn.net/thumb/C148x148/?fname=https://blog.kakaocdn.net/dn/dTfQMT/btqQE9mDYsD/Xhv7uDjiwQot72IKjeH5T1/img.png)
자바에서는 메모리 관리를 GC가 해주기 때문에 메모리 관리를 더 이상 신경 쓰지 않아도 된다고 생각할 수 있다. 하지만 GC의 영역에 벗어난 자원이 생성될 수 있으며, 이러한 자원이 생기지 않도록 주의해야 한다. 메모리 누수 케이스 1. 자기 자신의 메모리를 관리하는 클래스 이펙티브 자바에서는 Stack을 예로 든다. Stack은 객체 참조를 담는 저장소 풀을 만들어 원소들을 관리한다. 즉, 자기 자신의 메모리를 직접 관리한다. 문제는 저장소 풀에 등록된 원소들을 pop 할 때 생긴다. 일반적인 구현하는 pop의 로직은 Stack의 size를 -1 해주는 식으로 구현된다. 이때 Stack은 비활성화 영역에 다 쓴 참조를 가지게 되고, 메모리 누수의 원인이 된다. 다 쓴 참조(obselete referen..