JAVA 104

[아이템 13] clone 재정의는 주의해서 진행하라

Cloneable 인터페이스 Cloneable은 Object 클래스에 정의된 protected 메서드인 clone의 동작 방식을 결정하는 인터페이스입니다. Cloneable을 구현한 클래스의 인스턴스에서 clone을 호출할 경우 해당 객체의 필드들을 하나하나 복사한 객체를 반환하고 Clonable을 구현하지 않은 클래스에서 clone()을 호출할 경우 CloneNotSupportedException을 던집니다. 일반적으로 인터페이스를 구현한다는 것은 해당 클래스가 그 인터페이스에서 정의한 기능을 제공한다고 선언하는 행위인데 Cloneable의 경우 상위 클래스인 Object에 정의된 protected 메서드의 동작 방식을 변경한 것이기 때문에 인터페이스를 잘 못 사용한 예시라고 볼 수 있습니다. 정리하자..

JAVA/Effective Java 2024.01.29

[아이템 12] toString을 항상 재정의하라

모든 클래스는 암묵적으로 Object 클래스를 상속하기 때문에 별도로 toString 메서드를 오버라이딩하지 않았을 경우 Object의 toString 메서드를 사용합니다. 문제는 Object의 toString 메서드의 반환값이 아래와 같이 "[패키지를 포함한 클래스명]@[hashCode]" 형태를 띠기 때문에 유의미한 데이터가 아닙니다. toString은 보통 로깅할 때 사용되므로 간결하면서 사람이 읽기 쉬운 형태의 정보를 표출해야 하며 라이브러리의 도움을 받거나 직접 정의하는 방식을 선택해야 합니다. toString 구현 저자가 꾸준히 언급하는 구글의 AutoValue 혹은 Lombok의 도움을 통해 toString 구현이 가능합니다. 대부분 케이스에서는 Lombok에서 생성해주는 toString 메..

JAVA/Effective Java 2024.01.27

[아이템 11] equals를 재정의하려거든 hashCode도 재정의하라

앞서 아이템 10에서도 언급했다시피 equals를 오버라이딩했다면 hashCode 메서드도 같이 재정의해야 합니다. hashCode 메서드를 재정의하지 않을 경우 아래에 명시할 hashCode 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap 혹은 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것입니다. 두 객체에 대한 equals가 같다면, hashCode의 값도 동일해야 함 equals 비교에 사용하는 정보가 변경되지 않았다면 hashCode는 매번 같은 값을 반환 단, 정보가 변경되었거나 애플리케이션을 재기동했을 경우 변경될 수 있음 두 객체에 대한 equals가 다르더라도 hashCode의 값은 같을 수 있지만 해시 테이블 성능을 고려해 다른 값을 리턴하는 것이 좋음 ..

JAVA/Effective Java 2024.01.27

[아이템 10] equals는 일반 규약을 지켜 재정의하라

모든 클래스는 암묵적으로 Object 클래스를 상속하며 이에 따라 아래의 메서드를 오버라이딩 가능합니다. equals hashcode toString clone finalize 이번 게시글에서는 equals에 대해 알아보겠습니다. equals를 재정의할 필요 없는 케이스 아래의 케이스에 대해서는 equals를 재정의할 필요가 없습니다. 각 인스턴스가 본질적으로 고유 인스턴스의 "논리적 동치성"을 검사할 필요 없음 상위 클래스에서 재정의한 equals가 하위 클래스에도 적절 클래스가 private이거나 package-private이고 equals 메서드를 호출할 일 없음 1. 각 인스턴스가 본질적으로 고유 싱글톤으로 구현했거나 enum 클래스일 경우 본질적으로 고유한 인스턴스이기 때문에 비교를 하는 경우가..

JAVA/Effective Java 2024.01.26

[아이템 9] try-finally보다는 try-with-resources를 사용하라

Java 7부터 try-with-resources 구문이 등장해 try-finally는 더 이상 최선의 방법이 아닙니다. try-with-resources를 사용할 경우 장점은 아래와 같습니다.코드가 훨씬 간결해져 가독성이 좋아짐예외가 두 개 이상 발생했을 때 예외를 잡아먹지 않기 때문에 전부 확인 가능 코드가 훨씬 간결해져 가독성이 좋아짐자원이 하나인 경우 try-finally 절도 괜찮아 보이지만 자원이 두 개 이상이 되어 try-finally 절이 중첩이 되는 순간부터 가독성이 급격하게 안 좋아집니다. 단일 자원 다중 자원 다중 자원 코드를 보고 혹여나 아래와 같이 코드를 작성하면 단일 try-finally 절로 작성이 되지 않을까?라고 생각할 수 있겠지만 이렇게 작성할 경우 finally 절 내 ..

JAVA/Effective Java 2024.01.24

[아이템 8] finalizer와 cleaner 사용을 피하라

Java 8까지는 finalizer를 사용하여 자원을 정리했으며, Java 9부터는 cleaner가 도입되어 자원을 적절한 타이밍에 정리할 수 있도록 제공되었습니다. 기본적으로 Java에서는 객체가 더 이상 참조되지 않을 때 GC가 해당 객체를 수거하기 때문에 별도 처리를 안 해도 되는 케이스가 대부분이지만 파일이나 네트워크 리소스와 같은 외부 자원을 사용하는 객체의 경우, 해당 리소스를 명시적으로 해제해야 할 수 있습니다. 이를 위해 finalizer() 메서드와 cleaner가 기획되고 제공이 되었지만 아래에 열거할 이유들로 인해 이러한 메커니즘의 사용을 자제해야합니다. finalizer와 cleaner는 즉시 수행된다는 보장이 없음 finalizer와 cleaner는 실행되지 않을 수도 있음 fin..

JAVA/Effective Java 2024.01.23

[아이템 7] 다 쓴 객체 참조를 해제하라

객체 참조 해제는 기본적으로 GC가 해주지만 간혹 메모리 누수를 방지하기 위해 다 쓴 객체를 직접 참조 해제해야 하는 케이스가 있습니다. 책에서는 자기 메모리를 직접 관리하는 클래스의 경우 직접 참조를 해제해야 한다고 명시했고 대표적인 사례로 아래 세 가지 케이스를 예시로 들었습니다. Object 배열을 갖는 스택 캐시 리스너 혹은 콜백 1. Object 배열을 갖는 스택 아래 Stack 클래스와 같이 자기 메모리(Object 배열)를 직접 관리하는 케이스의 경우 객체 참조를 null로 할당하면서 직접 해제해야 합니다. 객체 참조를 null로 할당할 경우 GC가 돌 때 메모리를 회수할 수 있게 됩니다. 만약 pop() 메서드에서 위 코드와 같이 명시적으로 객체 참조를 해제하지 않고 아래와 같이 단순히 t..

JAVA/Effective Java 2024.01.22

[아이템 6] 불필요한 객체 생성을 피하라

저자는 아래의 세 가지 케이스에 대해서 불필요한 객체 생성을 피하라고 정리했습니다.문자열정규식 패턴오토 박싱 위 세 가지 케이스를 정리하기 전에 우선 하나를 명확히 짚고 가야 합니다. "아이템 6"의 제목만으로 객체 생성이 비싼 작업이라고 추측해서는 안 됩니다. 객체 생성 자체가 비싼 것은 아니기 때문에 위 세 가지 케이스를 제외하고는 얼마든지 객체를 생성해도 상관없습니다. 문자열JVM(Java Virtual Machine)은 내부적으로 문자열을 pool이라는 일종의 해시맵에 캐싱하고 다른 곳에서 동일한 문자열을 참조하려고 할 때 pool에서 꺼내 재사용하고 있습니다. 따라서 문자열은 굳이 new를 통해 동일한 문자열을 재생성하기보다는 문자열을 바로 할당하는 것이 메모리 측면에서 유리합니다. * 위 예제..

JAVA/Effective Java 2024.01.21

[아이템 5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

사용하는 자원에 따라 동작이 달라지는 클래스는 앞서 다루었던 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않습니다. 이러한 클래스는 Spring Framework를 공부했다면 지겹게 들었을 의존성 주입(Dependency Injection)이 적합합니다. 사용하는 자원에 따라 동작이 달라지는 클래스 책에서 예시로 든 맞춤법 검사기는 사전에 의존하는데 한영사전이냐 영한사전이냐에 따라 SpellChecker 클래스의 동작이 달라질 것입니다. 한영사전은 isValid() 메서드를 통해 한글 단어가 존재하는지 확인할 것이고 suggestions() 메서드를 통해 오타가 났을 때 가장 근접한 한글 단어를 추천 반면 영한사전은 isValid() 메서드를 통해 영어 단어가 존재하는지 확인할 것이고 suggestio..

JAVA/Effective Java 2024.01.20

[아이템 4] 인스턴스화를 막으려거든 private 생성자를 사용하라

객체지향임에도 불구하고 간혹 인스턴스를 생성하지 말라고 권장하는 케이스가 있습니다. 보통 static 한 메서드들만 가지고 있는 유틸성 클래스가 위 케이스에 해당합니다. 인스턴스화를 막는 방법은 아래와 같이 두 가지가 있습니다. private 생성자를 통해 인스턴스화 방지 abstract 클래스로 생성하여 인스턴스화 방지 이 방법은 상속을 통해 우회적으로 생성자를 호출할 수 있으므로 불완전한 방법 방법 1. private 생성자를 통해 인스턴스화 방지 public 혹은 protected 생성자 없이 private 생성자만 정의할 경우 같은 클래스 내 main 함수에서 호출하지 않는 이상 생성자를 호출할 수 없어 인스턴스화를 방지할 수 있습니다. 같은 클래스 내 main 함수에서도 호출하는 것을 방지하고 ..

JAVA/Effective Java 2024.01.20