클라이언트가 클래스의 인스턴스를 얻기 위해서 많이 사용하는 방법은 public 생성자이다. 하지만 클래스는 생성자와 별도로 정적 팩터리 메소드(static factory method)를 제공할 수 있다.정적 팩터리 메소드란 그 클래스의 인스턴스를 반환해주는 메서드이다.
정적 팩터리와 생성자에는 똑같은 제약이 하나 있다. 바로 선택적 매개변수가 많다면 적절하게 대응하기 어렵다는 것이다.예를 들어, 식품 포장의 영양정보를 표현하는 클래스를 생각해보자. 영양정보로 A, B, C, D....F.. 대략 20가지가 넘는 항목으로 나눠진다고 보
싱글턴 패턴이란, 한 클래스에 하나의 인스턴스만을 보장하는 패턴이다. 그러면 하나의 인스턴스만 사용하는 것이 어떤점이 좋을까?먼저 첫 번째로 메모리 절약이 가능하다는 점이다. 하나의 인스턴스를 생성하면 반복적으로 호출해도 따로 생성없이 만들어 놓은 인스턴스만을 가져오기
때론 정적 메서드와 정적 필드만을 담은 클래스를 만들고 싶을 수가 있다. 오로지 필드만을 담은 클래스라던가 아니면 메소드만 담은 클래스라던가 말이다.예를 들어, java.lang.Math와 java.util.Arrays 처럼 기본 타입 값이나 배열 관련 메서드들을 모아
많은 클래스가 하나 이상의 자원에 의존한다. 예를 들어, 맞춤법 검사기는 사전(dictionary)에 의존하는데. 이를 정적 클래스로 구현하는 것은 좋지 않다. 아래는 예시이다.정적 유틸리티싱글턴두 클래스 모두 유연하지 않고 테스트하기가 어렵다. 만약 사전을 다른 언어
똑같은 기능을 가진 객체를 매번 생성하는 것보다 객체 하나를 재사용하는 편이 나을 때가 많다. 다음은 불필요한 객체를 생성하는 예시들이다.String s = new String("test"); // 따라하지 말 것이 문장을 잘보면 왼쪽, 오른쪽 모두 객체를 생성한다.
Java에서는 메모리를 알아서 관리해주는* GC(garbage collection)*이 존재하기 때문에 사용자가 메모리 관리의 부담을 덜어주게 된다. 하지만 GC가 모든 메모리를 관리하지는 못한다. 자신이 직접 메모리를 관리하는 클래스의 경우 GC의 관리에서 벗어나게
자바에는 두 가지의 객체 소멸자를 제공합니다. finalizer와 cleaner인데. 이 두 가지의 사용은 피하는게 좋습니다. finalizer는 심각한 위험성을 가지고 있는데. 성능 저하, 오동작, 이식성 문제등 쓰면 안되는 여러가지 이유가 있습니다. finalize
자바 라이브러리에는 close 메서드를 직접 호출해서 닫아줘야 하는 자원이 많다. 하지만 사람이 하는지라 깜빡하고 못하는 경우가 대다수 일 것이다.안전망으로 finalizer를 활용하고 있지만 Item 8에서처럼 믿을만 하지 못하다.전통적으로 try-finally를 사
equals 메서드는 재정의하기 쉬워 보이지만 고려해야 할 것들이 많아 생각처럼 쉽지가 않다. 가능하면 재정의하지 않는 것을 권장한다.아래의 상황 중 하나라도 해당된다면 재정의하지 않는 것을 추천한다.각 인스턴스가 본질적으로 고유하다. 값(상태)을 표현하는 객체가 아
만약 당신이 equals를 재정의 했다면 hashCode도 재정의해라. 그렇지 않으면 hashCode 일반 규약을 어기게 될 것이다. 이는 HashMap, HashSet 같은 컬렉션을 사용할 때 문제가 생긴다.다음은 hashCode의 일반 규약이다.equals 비교에
Object의 기본 toString 메서드가 우리가 원하는 문자열을 반환하는 경우는 거의 없다. 그렇기 때문에 toString 일반 규약에 맞게 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보' 를 반환할 수 있도록 재정의를 하는게 좋다.equals와 hashCode
Comparable 인터페이스의 유일무이한 메서드인 compareTo를 살펴보자. copareTo는 두 가지 성격을 빼면 Object의 equals와 같다.첫 번째는 값의 동치성 비교와 더불어 순서를 비교할 수 있다.두 번째는 제네릭하다는 것이다.만약 Comparabl
어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 클래스의 내부 데이터와 구현 정보를 얼마나 잘 숨겼는지이다. 잘 설계된 컴포넌트의 경우, 모든 내부 구현 정보를 완벽히 숨겨 구현과 API를 깔끔하게 분리한다.오직 공개 API를 통해서만 소통하며 내부 동
public 클래스에는 public 필드를 사용하지 않아야 한다. 가능하면 접근자 메서드를 사용하라. 아래는 사용하면 안되는 예이다.이렇게 public으로 필드를 구성하면 외부에서 직접 접근할 수 있기 때문에 캡슐화의 이점을 상실하게 된다. 또 API를 수정하지 않고는
불변 클래스란, 한번 만들어진 인스턴스의 내부 값은 수정할 수 없는 클래스를 말한다.이 불변 클래스가 가지고 있는 정보는 객체가 파괴되기 전까지 절대 달라지지 않아야 한다. 자바에서 제공하는 불변 클래스의 예로는 String, 기본 타입의 박싱된 클래스, BigInte
상속은 코드를 재사용하는 강력한 수단이지만 최선은 아니다. 잘못 사용한다면 오류를 낼 수 있게 된다. 상위 클래스, 하위 클래스 모두 같은 프로그래머의 통제 안에 있는 클래스라면 상속을 해도 상관없다. 하지만 패키지 밖에 있는 클래스를 상속하는 일은 위험하다.이러한 상
상속을 고려한 설계와 문서화란 무엇일까?우선, 메서드를 재정의하면 내부적으로 어떤 역할을 하는지 정확히 정리하여 문서를 남겨야 한다. 달리 말하면 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야 한다. 클래스의 API로 공개된 메
이번에 볼 것은 추상 클래스와 인터페이스이다. 둘 모두 디폴트 메서드를 제공할 수 있게 되어 인스턴스 메서드를 구현 형태로 제공할 수 있다.이 둘의 가장 큰 차이점으로는 추상 클래스는 상속 받은 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다. 반면 인터페이스
자바 8전에는 인터페이스에 새로운 메서드를 추가하려면 이를 구현한 구현 클래스를 깨트리지 않고는 추가할 방법이 없었다. 만약 그렇지 않고 메서드를 추가하면 컴파일 에러가 발생할 것이다. 왜냐하면 구현 클래스에는 추가 메서드를 재정의하지 않았기 때문이다.이를 위해 디폴트
인터페이스는 자신을 구현한 클래스가 참조할 수 있는 타입 역할로만 사용해야 한다. 쉽게 말해 DI를 쓸 때 처럼, 인터페이스를 사용해서 구현 클래스를 담는 용도로 사용하고 클라이언트에 이 클래스의 인스턴스로 무엇을 할 수 있는지 설명하는 용도로만 사용해야 한다.이런 인
태그 달린 클래스란, 클래스 안에 Enum 타입이던 String에 값을 넣어 클래스를 구분하는 클래스를 말한다. 아래는 하나의 클래스 안에 태그로 원과 사각형을 구분하는 예시이다. (안좋은 예시)이 코드에는 단점이 한가득이다. 1\. 열거 타입 선언, 태그 필드, sw
이번 아이템에선 중첩 클래스(nested class)에 대한 내용이다. 중첩 클래스란, 다른 클래스 안에 정의된 클래스를 말한다. 이 중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 한다.중첩 클래스의 종류는 정적 맴버 클래스, 비정적 맴버 클래스, 익명 클래스,
이번은 제네릭에 대한 설명이다. 다음과 같이 제네릭 타입을 하나 정의하면 List<E> 이와 함께 로 타입(raw type)도 같이 정의된다. 그냥 List도 같이 만들어진다는 뜻이다.그러면 왜 만들어지는 것이고 왜 쓰면 안되는걸까?먼저 로 타입이 만들어지는 이유
먼저 비검사 경고란, 컴파일러의 경고를 나타낸다. 제네릭을 사용하면 이러한 비검사 경고가 많이 발생하는데. 최대한 줄일 수 있는 것이 좋다. 아래의 코드를 살펴보자.위의 코드를 그대로 컴파일하면 new HashSet()에 타입 매개변수를 명시하지 않았다는 경고가 발생한
배열과 제네릭 타입의 차이는 무엇일까? 크게 두 가지가 있는데. 바로 공변과 실체화이다. 먼저 공변이란 함께 변한다는 뜻인데. 만약 Super 타입이 있고 Sub 타입이 Super 타입의 하위 타입이라고 해보자. 그러면 Super\[] 에는 Super 타입뿐아니라 하위
이번 장에서는 일반적인 배열을 사용한 클래스를 제네릭 타입으로 바꾸는 과정을 배우게 된다. 아래의 코드는 Object를 활용한 단순한 스택 클래스이다. 이렇게 Stack을 구현하면 pop을 통해서 원소를 가져올 떄마다 형변환을 해줘야한다. 그러면 런타임 에러가 발생할
작성중
작성중