JAVA/Effective java
-
toString을 항상 재정의하라JAVA/Effective java 2021. 1. 19. 12:30
Object의 기본 toString 메서드가 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없다. 이 메서드는 단순히 클래스_이름@16진수로_표시한_해시코드 를 반환할 뿐이다. toString의 일반 규약에 따르면 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보'를 반환해야 한다. 이 같은 toString을 잘 구현한 클래스는 사용하기에 훨씬 즐겁고, 그 클래스를 사용한 시스템은 디버깅하기 쉽다. toString메서드는 객체를 println, printf, 문자열 연결, assert 구문에 넘길 때, 혹은 디버거가 객체를 출력할 때 자동으로 불리고 이는 직접 호출되지 않더라도 다른 어딘가에서 쓰일 거란 이야기이다. 또 작성한 객체를 참조하는 컴포넌트가 오류 메시지를 로깅할 때 자동으로 호..
-
equals를 재정의하려거든 hashCode도 재정의하라JAVA/Effective java 2021. 1. 14. 11:44
equals를 재정의한 클래스 모두에서 hashCOde도 재정의해야 한다. 그렇지 않는다면 hashCode 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. equals(Object0가 두 객체를 같다고 판단했다면 두 객체의 hashCode는 똑같은 값을 반환해야 하며 equals(Object) 가 두 객체를 다르다고 판단했더라도, 두 객체의 hashCode가 서로 다른 값을 반환할 필요는 없다. 단, 다른 객체에 대해서는 다른 값을 반환해야 해시 테이블의 성능이 좋아진다. 이 코드의 답은 null을 반환한다. PhoneNumber 클래스는 hashCode를 재정의하지 않았기 때문에 논리적 동치인 두 객체가 서로 다른..
-
equals는 일반 규약을 지켜 재정의 하라JAVA/Effective java 2021. 1. 11. 13:41
equals 메서드는 재정의하기 쉬워 보이지만 자칫 잘못된 결과를 초래할 수 있다. 따라서 가장 쉬운 길은 아예 재정의 하지 않는 것이다. 그냥 두면 그 클래스의 인스턴스는 오직 자신과만 같게 된다. 따라서 다음 열거한 상황 중 하나에 해당되면 재정의하지 않는 것이 최선이다. 1. 각 인스턴스가 본질적으로 고유할 때 값을 표현하는 게 아닌 동작하는 개체를 표현하는 클래스, Thread 클래스는 하나의 좋은 예다. 2. '논리적 동치성'을 검사할 일이 없을 때 Object에 기본 equals는 객체를 식별하기 위해 주소 값을 비교한다. 만일 Pattern에 equals나 String에 equals 등 '논리적 동치성'의 경우가 없을 경우 재정의 하지 않아도 된다. 3. 상위 클래스에 재정의한 equals가..
-
Try-Finally 대신 Try-with-Resource 사용하라JAVA/Effective java 2021. 1. 4. 10:31
자바 라이브러리에는 InputStream, OutputStream 그리고 java.sql.Connection과 같이 정리(close)가 가능한 리소스가 많다. 하지만 그런 리소스를 사용하는 클라이언트 코드가 보통 리소스 정리를 잘 안 하거나 잘못하는 경우가 있다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class FirstError extends RuntimeException { } public class SecondException extends RuntimeException { } public class MyResource implements AutoCloseable { public void doSomething() throws FirstEr..
-
Finalizer와 Cleaner는 피하라JAVA/Effective java 2021. 1. 3. 23:16
Finalizer는 예측 불가능하고, 위험하며, 대부분 불필요하다. 그걸 쓰면 이상하게 동작하기도 하고, 성능도 안 좋아지고, 이식성에도 문제가 생길 수 있다. Finalizer를 유용하게 쓸 수 있는 경우는 극히 드물다. finalizer는 GC가 돌때 호출이 되는데 언제 호출되는지 예측할 수 없다. GC에 대상이 된다고 해서 바로 GC가 되는 것이 아니기 때문이다. 다음의 코드는 run() 실행 후 1초 있다가 종료되게 된다. run() 호출후의 finalizerExample의 레퍼런스는 유효하지 않게 되지만 실행해보면 Clean Up을 실행하지는 않는다. GC에 대상은 되지만 바로 되지는 않는다. 그럼 언제 써야 될까? 딱 두가지 경우 안전망 역할로 자원을 반납하고자 하는 경우. 네이티브 리소스를 ..
-
더이상 쓰지 않는 객체 레퍼런스는 없애자 + Weak ReferenceJAVA/Effective java 2021. 1. 2. 20:41
메모리 직접 관리 자바에 GC (가비지 콜렉터)가 있기 때문에 메모리 관리에 대해 신경 쓰지 않아도 될 거라고 생각하기 쉽지만 그렇지 않다. 다음 코드를 살펴보자. 여기서의 size는 index에 역할을 하고 있다. pop()을 보면 내가 넣을 장소가 아닌 뺄 장소로 이동해야 하기 때문에 먼저 --size를 하고 반환한다. 배열은 계속해서 값을 넣기만 하고 없어지지는 않는다. 스택에 계속 쌓다가 많이 빼냈다고 치자, 그래도 스택이 차지하고 있는 메모리는 줄어들지 않는다. 왜냐면 저 스택의 구현체는 필요없는 객체에 대한 레퍼런스를 그대로 가지고 있기 때문이다. 가용한 범위라는 것은 실제 유의미한 element를 가지고 있는 범위이고 이는 size 보다 작은 부분들이다. 그 값 보다 큰 부분에 있는 값들은 ..
-
불필요한 객체를 만들지 말자JAVA/Effective java 2021. 1. 1. 22:37
기능적으로 동일한 객체를 새로 만드는 대신 객체 하나를 재사용하는 것이 대부분 적절하다. 재사용하면 새로운 객체를 만들지 않기 때문에 성능적으로 더 빠르다. 그리고 불변 객체들은 항상 재사용할 수 있다. 문자열 객체 생성 자바의 문자열, String을 new로 생성하면 항상 새로운 객체를 만들게 된다. == 로 주소값을 비교한 name과 name2의 값은 false가 나온다. name에서 힙에 메모리가 할당되고 new로 또 다시 생성했기 때문에 name2에서 새로운 메모리가 할당되어 힙에 생성된다. 따라서 다음과 같이 String 객체를 생성하는 것이 올바르다. String s = "bikini"; 문자열 리터럴을 재사용하기 때문에 해당 자바 가상 머신에 동일한 문자열 리터럴이 존재한다면 그 리터럴을 재..
-
리소스를 엮을 때는 의존성 주입을 선호하라JAVA/Effective java 2020. 12. 31. 18:28
대부분의 클래스는 여러 리소스에 의존한다. 여기서 말하는 리소스는 의존성이다. 이 책에서는 SpellChecker와 Dictionary를 예로 들고 있다. SpellChecker 클래스는 스펠링이 맞는지 확인하는 클래스이고 Dictionary는 사전 클래스이다. 이때 SpellCheck가 Ditionary를 사용하고, 이를 의존하는 리소스 또는 의존성이라고 부른다. 이때 SpellChecker를 다음과 같이 구현하는 경우가 있다. 부적절한 구현 static 유틸 클래스 static 유틸리티 클래스이고 인스턴스로 만들 이유가 없기에 private 한 생성자를 만들었다. public static 한 메서드를 사용해서 클라이언트들이 SpellChecker.isValid 식으로 유틸 클래스를 사용하도록 한다. ..