728x90

Effective Java 8

Effective Java 3/E - 6장 열거 타입과 애너테이션 - 2

39. 명명 패턴보다 애너테이션을 사용하라 명명 패턴의 단점 오타가 나면 안 된다. 올바른 프로그램 요소에서만 사용된다는 보장이 없다. 프로그램 요소를 매개변수로 전달할 마땅한 방법이 없다. 애너테이션 선언 일반적인 정의 방법 public @interface Sample { } JUnit에서 사용하는 @Test 애너테이션 @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @API(status = STABLE, since = "5.0") @Testable public @interface Test { } 메타 애너테이션 애너테이션 선언에 다는 애너테이션 @Reten..

Effective Java 3/E - 6장 열거 타입과 애너테이션 - 1

34. int 상수 대신 열거 타입을 사용하라 정수 열거 패턴의 단점 표현하기 복잡해진다. 타입 안전을 보장할 방법이 없다. 같은 값을 가지는 다른 값과 동등 비교시 컴파일러 단계에서 걸러낼 방법이 없다. 문자열로 출력하기 어렵고, 같은 열거 그룹의 값들에 대한 순회 방법이 마땅치 않다. 문자열 상수를 적용해도(문자열 열거 패턴), 출력하는 것 이상의 효과가 없고 하드코딩을 피할 수 없다. Enum 자바의 Enum은 완전한 형태의 클래스라서 다른 언어들과 비교해볼 때 더 강력한 Enum이다. Enum 타입 자체는 클래스고, 상수 하나당 자신의 인스턴스를 만들어 public static final로 공개한다. 밖에서 접근 가능한 생성자를 제공하지 않아, 사실상 final이다. 사실상 싱글턴을 일반화한 형태..

Effective Java 3/E - 5장 제네릭 - 2

30. 이왕이면 제네릭 메서드로 만들라 메서드도 제네릭 메서드로 생성이 가능하다. 다음과 같은 정적 유틸리티 메서드가 제네릭 메서드의 대표적인 예시다. 타입 매개변수들을 선언하는 매개변수 목록은 메서드의 제한자와 반환 타입 사이에 위치한다. public static int binarySearch(List, Object>)를 사용하는데, Map 자체가 아닌 Key에 와일드카드 타입을 사용하고 있어서, 아무 타입이나 넣을 수 있다. 즉, 모든 키가 서로 다른 매개변수화 타입으로, 다양한 타입을 지원할 수 있다. Object인 Value - 모든 값이 Key로 명시한 타입임을 보장하지 않음 getFavorite의 type.cast Value는 Object이나 실제 반환은 T가 되어야 하므로, cast를 수행 ..

Effective Java 3/E - 5장 제네릭 - 1

26. Raw Type은 사용하지 말라 클래스와 인터페이스 선언에 타입 매개변수가 쓰이면 제네릭 클래스/인터페이스라고 한다. 제네릭 클래스와 인터페이스를 합쳐 제네릭 타입이라고 한다. 각 제네릭 타입은 매개변수화 타입을 정의하며, 안에 실제 타입 매개변수를 나열한다. 제네릭 타입을 하나 정의하면 Raw 타입, 타입 매개변수를 전혀 사용하지 타입이 정의된다. Raw Type 사용으로 인해, 제네릭이 가져오는 안전성과 표현력을 모두 상실한다. List와 List는 엄연히 다르다. List는 컴파일러에 모든 타입 허용을 명확히 전달한 것 List는 제네릭에서 완전히 벗어난 것 List는 Raw Type의 하위 타입이지만, 타입을 명시한 List의 하위는 아님 원소의 타입을 몰라도 되는 경우가 필요하다면 Lis..

Effective Java 3/E - 4장 클래스와 인터페이스 - 3

23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 태그 달린 클래스의 단점 열거 타입 선언, 태그 필드, switch 문 등의 관련 코드가 필요 필드들을 final로 선언하는 경우, 쓰이지 않는 필드까지 생성자에서 초기화 인스턴스의 타입만으로는 현재 의미 파악 불가 의미 없는 코드로 가독성이 떨어지면서 필요 없는 코드 작성 과정에서 오류 발생 가능성과 비효율적인 작업이 급격하게 증가하게 된다. 이러한 문제를 해결하기 위해서는 서브타이핑(Subtyping)을 사용하는 것이 좋다. 태그 달린 클래스의 예시 public class Figure { enum Shape { RECTANGLE, CIRCLE }; final Shape shape; // 관련 필드가 한 곳에다 모여 있다. double lengt..

Effective Java 3/E - 4장 클래스와 인터페이스 - 2

18. 상속보다는 컴포지션을 사용하라 상속은 코드 재사용의 강력한 수단이지만, 잘못된 사용은 오히려 오류를 유발한다. 다른 패키지의 구체 클래스를 확장하여 사용하는 상속은 위험한 행위가 된다. 상속은 캡슐화를 깨뜨린다. 상위 클래스의 구현에 따라서, 하위 클래스 동작에 이상이 발생할 수 있다. 상위 클래스는 릴리즈마다 내부 구현이 변경될 수 있는데, 이를 확장한 하위 클래스에서는 어떠한 변경 사항 없이도 동작에 문제가 발생할 수 있다. HashSet을 상속하여 사용하는 구조 예시 public class InstrumentedHashSet extends HashSet { public int addCount = 0; public InstrumentedHashSet() {} public Instrumented..

Effective Java 3/E - 4장 클래스와 인터페이스 - 1

15. 클래스와 멤버의 접근 권한을 최소화하라 아주 기본적인 내용이지만, 처음 입문했을 때 모든 내부 구현 정보를 외부에 제공하던 설계를 만들었던 시기가 생각나는 아이템이었다. 결론적으로, 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨서 구현과 API를 깔끔히 분리하고, 오직 API를 통해서만 다른 컴포넌트와 소통하고 내부의 동작에는 상호 개의치 않는 설계가 필요하다. 우리가 흔히 이야기하는 이 개념은 정보 은닉, 캡슐화로, 설계의 근간이다. 장점 시스템 개발 속도를 높인다. 여러 컴포넌트가 병렬로 개발할 수 있기 때문에 시스템 관리 비용을 낮춘다. 컴포넌트를 더 빨리 파악해, 디버깅하고 다른 컴포넌트로의 교체도 부담 적음 성능 최적화 단계에서 도움이 될 수 있다. 완성된 시스템을 프로파일링해 최적..

Effective Java 3/E - 3장 모든 객체의 공통 메서드

Object는 객체를 만들 수 있는 구체 클래스로, 상속하여 사용하는 것을 기본으로 하고 있다. Object의 final이 아닌 메서드들은 모두 재정의를 염두에 두고 설계되어 있어 이에 맞게 재정의해야 한다. 10. equals는 일반 규약을 지켜 재정의하라 equals를 잘못 재정의하면 문제를 발생시키므로, 대응하기 위한 방법 중 가장 쉬운 것은 하지 않는 것이다. 다음 케이스에 대해서는 재정의하지 않는 것이 좋다. 재정의하지 않아도 되는 경우 각 인스턴스가 본질적으로 고유한 경우 Thread 클래스 같은, 어떤 행위를 하는 클래스들이 이에 해당한다. 인스턴스의 논리적 동치성을 검사할 필요가 없는 경우 java.util.regex.Pattern은 두 인스턴스가 같은 regex인지 확인하도록 재정의했다...

728x90