대부분의 열거 타입 상수는 자연스럽게 하나의 정숫값에 대응됩니다. 그리고 모든 열거 타입은 해당 상수가 그 열거 타입에서 몇 번째 위치인지를 반환하는 ordinal이라는 메서드를 제공합니다. 이런 이유로 열거 타입 상수와 연결된 정숫값이 필요하면 ordinal 메서드를 이용하고 싶은 욕구에 빠집니다. 다음 코드는 합주단의 종류를 연주자가 1명인 솔로부터 10명까지 정의한 열거 타입입니다. public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; public int numberOfMusicians() { return oridnal() + 1; } } 동작은 하지만 유지보수하기가 끔찍한 코드입..
열거 타입은 일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입입니다. 사계절, 태양계의 행성, 카드게임의 카드 종류 등을 생각하시면 이해가 빠르실 겁니다. 정수 열거 패턴 기법 (옛날 방식) 자바에서 열거 타입을 지원하기 전에는 다음 코드처럼 정수 상수를 한 묶음 선언해서 사용했었습니다. // 상당히 취약한 정수 열거 패턴 public static final int APPLE_FUJI = 0; public static final int APPLE_PIPPIN = 1; public static final int APPLE_GRANNY_SMITH = 2; public static final int ORANGE_NAVEL = 0; public static final int ORANGE_T..
제네릭은 Set, Map 등의 컬렉션과 ThreadLocal, AtomicReference 등의 단일원소 컨테이너에도 흔히 쓰입니다. 이런 모든 쓰임에서 매개변수화되는 대상은 (원소가 아닌) 컨테이너 자신입니다. 따라서 하나의 컨테이너에서 매개변수화할 수 있는 타입의 수가 제한됩니다. 컨테이너의 일반적인 용도에 맞게 설계된 것이니 문제될 건 없습니다. 예컨대 Set에는 원소의 타입을 뜻하는 단 하나의 타입 매개변수만 있으면 되며, Map에는 키와 값을 타입을 뜻하는 2개만 필요한 식입니다. 하지만 더 유연한 수단이 필요할 때도 종종 있습니다. 예컨대 데이터베이스의 행(row)은 임의 개수의 열(column)을 가질 수 있는데, 모두 열을 타입 안전하게 이용할 수 있다면 멋질 것입니다. 다행히 쉬운 해법이..
가변인수(varargs) 메서드(아이템 53)와 제네릭은 자바 5 때 함께 추가되었으니 서로 잘 어우러지리라 기대하겠지만, 슬프게도 그렇지 않습니다. 가변인수는 메서드에 넘기는 인수의 개수를 클라이언트가 조절할 수 있게 해주는데, 구현 방식에 허점이 있습니다. 가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어집니다. 그런데 내부로 감춰야 했을 이 배열을 그만 클라이언트에 노출하는 문제가 생겼습니다. 그 결과 varargs 매개변수에 제네릭이나 매개변수화 타입이 포함되면 알기 어려운 컴파일 경고가 발생합니다. 아이템 28에서 실체화 불가 타입은 런타임에는 컴파일타임보다 타입 관련 정보를 적게 담고 있음을 배웠습니다. 그리고 거의 모든 제네릭과 매개변수화 타입은 실체화되지 않습니다..
아이템 28에서 이야기했듯 매개변수화 타입은 불공변입니다. 즉, 서로 다른 타입 Type1과 Type2가 있을 때 List은 List의 하위 타입도 상위 타입도 아닙니다. List은 List의 하위 타입이 아니라는 뜻인데, 곰곰이 따져보면 사실 이쪽이 말이 됩니다. List에는 어떤 객체든 넣을 수 있지만 List에는 문자열만 넣을 수 있습니다. 즉, List은 List가 하는 일을 제대로 수행하지 못하니 하위 타입이 될 수 없습니다. ⇒ 리스코프 치환 원칙에 어긋납니다. (아이템 10) SOLID [3]. 리스코프 치환 원칙 ‘개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴' 책을 보고 정리한 글입니다. 리스코프 치환 원칙은 개방 폐쇄 원칙을 받쳐 주는 다형성에 관한 원칙을 제공한다. 리스코프 치..
클래스와 마찬가지로, 메서드도 제네릭으로 만들 수 있습니다. 매개변수화 타입을 받는 정적 유틸리티 메서드는 보통 제너릭입니다. 예컨대 Collections의 '알고리즘' 메서드(binarySearch, sort 등)는 모두 제네릭입니다. 제네릭 메서드 작성법은 제네릭 타입 작성법과 비슷합니다. 다음은 두 집합의 합집합을 반환하는, 문제가 있는 메서드입니다. public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); result.addAll(s2); return result; } 컴파일은 되지만 경고가 두 개 발생합니다. Union.java:5: warning: [unchecked] unchecked call to HashSet(Coll..
JDK가 제공하는 제네릭 타입과 메서드를 사용하는 일은 일반적으로 쉬운 편이지만, 제네릭 타입을 새로 만드는 일은 조금 더 어렵습니다. 그래도 배워두면 그만한 값어치는 충분히 합니다. 아이템 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_INITAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; }..
배열과 제네릭 타입에는 중요한 차이가 두 가지 있습니다. 첫 번째, 배열은 공변(convariant)입니다. 어려워 보이는 단어지만 뜻은 간단합니다. Sub가 Super의 하위 타입이라면 배열 Sub[]는 배열 Super[]의 하위 타입이 됩니다. 반면, 제네릭은 불공변(invariant)입니다. 즉, 서로 다른 타입 Type1과 Type2가 있을 때, List은 List의 하위 타입도 아니고 상위 타입도 아닙니다. 이것만 보면 제네릭에 문제가 있다고 생각할 수도 있지만, 사실 문제가 있는건 배열 쪽입니다. 다음은 문법상 허용되는 코드입니다. Object[] objectArray = new Long[1]; objectArray[0] = "타입이 달라 넣을 수 없다."; // ArrayStoreExcept..
- Total
- Today
- Yesterday
- 백준
- JPA
- BAEKJOON
- Algorithm
- 코테
- 이펙티브 자바
- 객체지향
- Effective Java
- MSA
- kkoon9
- Spring Boot
- 정규표현식
- 디자인 패턴
- 알고리즘
- node.js
- kotest
- BOJ
- Spring
- Kotlin
- C++
- 디자인패턴
- Olympiad
- 이팩티브 자바
- 테라폼
- 클린 코드
- programmers
- 클린 아키텍처
- 프로그래머스
- AWS
- Java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |