[이펙티브 자바] 10. equals는 일반 규약을 지켜 재정의하라

1. 개념 equals를 단순히 재정의 하는 것은 쉽지만 함정이 많다. 이번 장에서는 equals를 재정의 할 때 고려해야 하는 점과, 재정의가 완료된 후 확인해야 하는 부분들에 대해 다루고 있다. 2. equals를 재정의하는 경우와 재정의하지 말아야 하는 경우 2-1. equals를 재정의하지 말아야 할 경우 각 인스턴스가 본질적으로 고유한 값을 표현하는 클래스: 예를 들어, Thread 클래스는 각 인스턴스가 고유한 ID를 가지므로 equals를 재정의할 필요가 없다. 논리적 동치성 검사가 필요 없는 경우: 대부분의 경우 객체 식별성만 중요하며, 논리적 동치성은 필요하지 않을 수 있다. 상위 클래스에서 재정의한 equals가 하위 클래스에 적절한 경우: 상위 클래스에서 이미 equals를 적절히 구현했고, 이를 하위 클래스에서 그대로 사용해도 무방한 경우이다. 접근이 제한된 클래스: equals를 호출할 일이 없는 private이나 package-private 클래스일 경우, 재정의할 필요가 없다. 2-2. equals를 재정의해야 할 경우 논리적 동치성 비교가 필요한 경우: 객체의 내용이 같은지를 비교해야 할 때, 상위 클래스의 equals가 이를 충족시키지 않을 때 재정의가 필요하다. 3. equals 메서드의 규약 Object 기본 명세의 equals 메서드는 다음의 규약을 준수해야 한다: ...

June 29, 2024 · Jun Kang

[이펙티브 자바] 9. try-finally 보다는 try-with-resources를 사용하라

1. 개념 자바 라이브러리에는 close 메서드를 직접 호출해서 닫아줘야 하는 자원이 많다. 대표적으로 InputStream, ouputStream java.sql.connection 등이 있으며 해당 자원들은 클라이언트에서 놓치기 쉬워 예측할 수 없는 성능 문제로 이어지곤 한다. 이중 상당 수가 finalizer를 안정망으로 사용하여 문제에 대비하고 있긴 하지만, 완전히 안전하다고 할 수 없다. (해당 내용은 다음 포스트에서 확인 가능) [이펙티브 자바] - [이펙티브 자바] 8. finalizer와 cleaner 사용을 피하라 흔히 사용하는 try-finally를 사용한 예외처리를 확인해보자 2. try-finally 2-1. 자원을 1개 사용하는 try-finally 메서드 static String firstLineOfFile(String path) throws IOException { BufferdReader br = new BufferedReader(new FileReader(Path)); try { return br.readLine(); } finally { br.close(); } } ...

April 6, 2024 · Jun Kang

[이펙티브 자바] 8. finalizer 와 cleaner 사용을 피하라

1. finalizer와 cleaner란? finalizer와 cleaner는 자바의 2가지 객체 소멸자이다. finalizer는 Object.finalize() 메서드를 오버라이딩 함으로써 사용된다. 작동 여부 및 시점을 예측할 수 없고 상황에 따라 위험할 수 있어 일반적으로 불필요하며, 기능의 잘못된 동작, 낮은 성능, 이식성 문제의 원인이 되기도 한다. 기본적으로는 사용하면 안 되고, 자바 9에서는 finalizer를 deprecated API로 지정하고, java.lang.ref.Cleaner 클래스를 사용하여 구현된 cleaner를 대안으로 제시하였으나, cleaner 또한 finalizer보다는 덜 위험 하지만 여전히 예측불가하고 성능이 좋지 않아 일반적으로 불필요하다. ...

March 31, 2024 · Jun Kang

[이펙티브 자바] 7. 다 쓴 객체 참조를 해제하라

1. 메모리 관리 자바에선 가비지 컬렉터가 다 쓴 객체를 알아서 회수해 가기에 편리하고 효율적으로 메모리를 관리할 수 있다. 하지만 메모리 관리에 신경 쓰지 않아도 된다는 말은 절대 아니다. 메모리를 적절하게 관리하지 못하면 메모리 누수가 발생하고 심하면 프로그램이 종료될 수 있다. 메모리를 적절하게 관리하지 못하는 경우의 예제를 살펴보자. 다음은 스택을 간단하게 구현한 자바 코드이다. public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } 이대로 사용하여도 기능상으로는 전혀 문제가 없을 것이고, 어떤 테스트도 훌륭하게 통과하겠지만, 이 스택을 사용하는 프로그램을 오래 실행시킬 경우 가비지 컬렉션과 메모리 사용량이 늘어나 결국 성능이 저하될 것이다. ...

March 27, 2024 · Jun Kang

[이펙티브 자바] 6. 불필요한 객체 생성을 피하라

1. 객체의 재사용 똑같은 객체를 매번 새로 생성하는 것보다 하나를 생성 후 재사용하는 것이 훨씬 효율적이다. 특히 불변 객체는 언제든 재사용이 가능하다. 다음은 객체 생성 시 사용하면 안 되는 극단적인 예이다. String s = new String("bikini"); 보기만 해도 불편한 이 생성방식은 실행될 때마다 String 객체를 새로 생성한다. 이후에 기능적으로는 동일하게 사용되지만 큰 반복문이나 자주 호출되는 메서드 안에 있다면 쓸모없는 인스턴스가 여러 개 생성될 것이다. 개선된 객체 생성 방식을 확인해 보자. ...

March 26, 2024 · Jun Kang