전체 글 573

[Effective Java]12.toString을 항상 재정의하라

이번 아이템은 별 내용이 없고 프로그래머의 편의성을 위한 파트이다. Object의 기본 toString 메서드는 우리가 작성한 클래스에 적합한 문자열을 반환하는 경우는 거의 없다 이 메서드는 PhoneNumber@adbbd처럼 단순히 클래스_이름@16진수로_표시한_해시코드를 반환할 뿐이다. toString의 일반 규약에 따르면 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보'를 반환해야 한다. PhoneNumber@adbbd는 간결하고 읽기 쉽다고 볼 수 있지만 707-867-5309처럼 전화번호를 직접 알려주는 형태가 훨씬 유익한 정보를 담고 있다. 또한 toString의 규약은 "모든 하위 클래스에서 이 메서드를 재정의하라"고 한다. toString을 잘 구현한 클래스는 사용하기에 훨씬 즐겁고 디버..

Book/Effective Java 2022.06.04

[Effective Java]11.equals를 재정의하면 hashCode도 재정의하라

equals를 재정의한 클래스 모두 hashCode도 재정의해야 한다. 그렇지 않으면 hashCode 일반 규약을 어기게되어 해당 클래스의 인스턴스를 HashMap 이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. 다음은 Object 명세에서 발췌한 규약이다. - equals 비교에 사용되는 정보가 변경되지 않았다면 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다. - equals(Object)가 두 객체를 같다고 판단했다면 두 객체의 hashCode는 똑같은 값을 반환해야 한다. - equals(Object)가 두 객체를 다르다고 판단했더라도..

Book/Effective Java 2022.06.04

[Effective Java]10.equals는 일반 규약을 지켜 재정의하라

이전에 equals, hashCode, toString에 대해서 정리한 적이 있으나 고려하지 않은 부분이 많은 것 같아 작성한다. equals 메서드는 재정의하기 쉬워보이지만 곳곳에 함정이 도사리고 있어서 자칫하면 끔찍한 결과를 초래한다. 문제를 회피하는 가장 쉬운 길은 아예 재정의하지 않는 것이다. 그냥 두면 그 클래스의 인스턴스는 오직 자기 자신과만 같게 된다. 따라서 다음에서 열거한 상황 중 하나에 해당된다면 재정의하지 않는 것이 최선이다. 1.각 인스턴스가 본질적으로 고유하다. 값을 표현하는 게 아니라 동작하는 개체를 표현하는 클래스가 여기 해당한다. Thread가 좋은 예로 Object의 equals 메서드는 이러한 클래스에 딱 맞게 구현되었다. 2.인스턴스의 '논리적 동치성'을 검사할 일이 없..

Book/Effective Java 2022.06.04

홀수 홀릭 호석

📍 문제 설명 https://www.acmicpc.net/problem/20164 20164번: 홀수 홀릭 호석 호석이는 짝수랑 홀수 중에서 이니셜이 같은 홀수를 더 좋아한다. 운전을 하던 호석이는 앞차의 번호판이 홀수로 가득할 때 사랑스러움을 느낄 정도이다. 전화번호도 홀수만 있고 싶다. 그렇게 www.acmicpc.net 💡 접근 수가 세 자리 이상일 때 각 자릿수에 따라서 규칙을 찾아보니 substring으로 분할하면 임의의 모든 위치로 끊을 수 있었다. 끊은 위치를 기준으로 반복해야하므로 재귀함수를 사용했고 수가 한자릿수일 때 min과 max를 갱신시켜주고 cnt를 리셋시켜줬다. 👩‍💻 코드 import java.io.BufferedReader; import java.io.IOException; ..

Algorithm/baekjoon 2022.06.04

[Effective Java] 9.try-finally보다는 try-with-resources를 사용하라

자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다. InputStream, OutputStream, java.sql.Connection 등이 좋은 예다. 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 한다. 이런 자원 중 상당수가 안전망으로 finalizer를 활용하고는 있지만 finalizer는 그리 믿을만 하지 못하다. 전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였다. // 코드 9-1 try-finally - 더 이상 자원을 회수하는 최선의 방책이 아니다! (47쪽) static String firstLineOfFile(String path) throws IOException { BufferedReader ..

Book/Effective Java 2022.06.03

[Effective Java] 8.finalizer와 cleaner 사용을 피하라

자바는 두 가지 객체 소멸자를 제공한다. 그 중 finalizer는 예측할 수 없고 상황에 따라 위험할 수 있어 일반적으로 불필요하다. 오동작, 낮은 성능, 이식성 문제의 원인이 되기도 한다. finalizer는 나름의 쓰임새가 몇 가지 있긴 하지만 기본적으로 '쓰지 말아야' 한다. 그래서 자바 9에서는 finalizer를 deprecated API로 지정하고 cleaner를 그 대안으로 소개했다. 하지만 자바 라이브러리에서도 finalizer를 여전히 사용한다.. cleaner는 finalizer보다는 덜 위험하지만 여전히 예측할 수 없고 느리고 일반적으로 불필요하다. finalizer와 cleaner는 즉시 수행된다는 보장이 없다. 객체에 접근할 수 없게 된 후 finalizer나 cleaner가 실..

Book/Effective Java 2022.06.03

[Effective Java] 7.다 쓴 객체 참조를 해제하라

가비지 컬렉터가 메모리 관리를 해주니 메모리 관리에 더 이상 신경쓰지 않아도 된다고 오해할 수 있는데 절대로 사실이 아니다. 스택을 간단히 구현한 다음 코드를 보면서 메모리 누수가 일어나는 위치가 어디인지 확인해보자 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 Objec..

Book/Effective Java 2022.06.03

[Effective Java] 6.불필요한 객체 생성을 피하라

똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 특히 불변 객체(아이템 17)는 언제든 재사용할 수 있다. 다음 코드는 하지 말아야할 극단적인 예이다. String s = new String("bikini"); // 따라 하지 말 것! 이 문장은 실행될 때 마다 String 인스턴스를 새로 만들어 HEAP 영역에 할당된다. 완전히 쓸데없는 행위이므로 아래와 같이 사용하자. String s = "bikini"; 생성자 대신 정적 팩터리 메서드를 제공하는 불변 클래스에서는 정적 팩터리 메서드를 사용해 불필요한 객체 생성을 피할 수 있다. 예컨대 Boolean(String) 생성자 대신 Boolean.valueOf(String) 팩터리 메서드를 사용하는 것이 좋다. 그래..

Book/Effective Java 2022.06.03

[Effective Java] 5.자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

많은 클래스가 하나 이상의 자원에 의존한다. 가령 맞춤법 검사기는 사전에 의존하는데 이런 클래스를 정적 유틸리티 클래스로 구현한 모습을 드물지 않게 볼 수 있다. 정적 유틸리티를 잘못 사용한 예 - 유연하지 않고 테스트하기 어렵다. public class SpellChecker { private static final Lexicon dictionary = ...; private SpellChecker() {} // 객체 생성 방지 public static boolean isValid(String word) { ... } public static List suggestions(String typo) { ... } } 비슷하게 싱글턴으로 구현하는 경우도 흔하다. 싱글턴을 잘못 사용한 예 - 유연하지 않고 테..

Book/Effective Java 2022.06.03

[Effective Java] 4.인스턴스화를 막으려거든 private 생성자를 사용하라

단순히 정적 메서드와 정적 필드만을 담은 클래스를 만들고 싶을 때가 있을 것이다. 객체 지향적으로 사고하지 않는 이들이 종종 남용하는 방식이지만 나름의 쓰임새가 있다고한다. 정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰라고 설계한 것이 아니다. 하지만 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자를 만들어준다. 사용자의 입장에서는 생성자가 자동 생성된 것인지 구분할 수 없다. 실제 공개된 API들 중에서도 이처럼 의도치 않게 인스턴스화할 수 있게 된 클래스가 종종 있다고 한다. 추상 클래스로 만드는 것은 인스턴스화를 막을 수 없다. 하위 클래스를 만들어서 그것을 인스턴스화할 수 있기 때문이다. 이를 본 사용자는 상속해서 쓰라는 뜻으로 오해할 수 있으니 더 큰 문제일 수 있다. 따라서..

Book/Effective Java 2022.06.03