본문 바로가기

Dev Books/Effective Java32

[item 32] 제네릭과 가변인수를 함께 쓸 때는 신중하라 1. 가변인수와 제네릭을 혼용하면 타입 안정성이 흔들린다.가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어진다. 그런데 내부로 감춰야 했을 이 배열을 그만 클라이언트에 노출하는 문제가 생겼다. 그 결과 varags 매개변수에 제네릭이나 매개변수화 타입이 포함되면 알기 어려운 컴파일 경고가 발생한다. ✔️ 예시 : 제네릭과 varags를 혼용하면 타입 안정성이 깨진다.매개변수화 타입의 변수가 타입이 다른 객체를 참조하면 힙 오염이 발생한다. 다음 메서드를 예로 생각해보자. 이 메서드에서는 형변환하는 곳이 보이지 않는데도 인수를 건네 호출하면 ClassCastException을 던진다. 마지막 줄에 컴파일러가 생성한 (보이지 않는) 형변환이 숨어 있기 때문이다. .. 2025. 2. 6.
[item 31] 한정적 와일드카드를 사용해 API 유연성을 높여라 매개변수화 타입의 불공변매개변수화 타입은 불공변(invariant)이다. 서로 다른 타입 Type1과 Type2가 있을 때 List은 List의 하위 타입도 상위 타입도 아니다. 즉, List은 List의 하위 타입이 아니다라는 뜻이다.매개변수화 타입은 리스코프 치환 원칙에 어긋난다. List은 List가 하는 일을 제대로 수행하지 못하니 하위 타입이 될 수 없다. List은 String 문자열만 넣을 수 있다.예시 : Stack의 pushAll()Stack의 pushAll()을 작성하여 일련의 원소를 스택에 넣으려고 한다. Iterable src의 원소 타입이 스택의 원소 타입과 일치하면 잘 작동한다. import java.util.*;// Generic stack with bulk meth.. 2025. 2. 5.
[item 30] 이왕이면 제네릭 메서드로 만들라. 클래스와 마찬가지로, 메서드도 제네릭으로 만들 수 있다. 로 타입과 제네릭 메서드의 차이점을 이해하고, 제네릭 메서드로 변환했을 때 타입 안정성을 갖는 이점을 이해해보자.로 타입 사용 로(raw) 타입을 사용하고 있어 컴파일 시 경고가 발생한다. 로 타입은 제네릭 타입에서 타입 매개변수를 지정하지 않은 상태를 의미하며, 이는 타입 안전성을 저해하고 예상치 못한 오류를 유발할 수 있다. 따라서 제네릭 메서드로 변환하여 타입 안전성을 확보하는 것이 좋다. 제네릭 메서드로 변환된 코드 경고를 없애려면 위와 같이 타입 매개변수 목록을 , 반환타입을 Set으로 명시하면 된다. ✅ 제네릭 메서드 만들기제네릭 메서드는 메서드 선언 시 타입 매개변수를 명시하여, 해당 메서드가 다양한 타입의 매개변수.. 2025. 2. 4.
[item 29] 이왕이면 제네릭 타입으로 만들라. 제네릭 타입을 만들기 전에, 제네릭이 없는 Stack 코드를 살펴보자. import java.util.Arrays;import java.util.EmptyStackException;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++] .. 2025. 2. 4.