제네릭(Generics)
// 제네릭 클래스 정의
class Notepad<T> {
private T memo;
public void setMemo(T memo) {
this.memo = memo;
}
public T getMemo() {
return memo;
}
}
// 제네릭 클래스 사용
public class Main {
public static void main(String[] args) {
Notepad<String> stringBox = new Notepad<>();
stringBox.setMemo("Hello");
System.out.println(stringBox.getMemo()); // Hello
Notepad<Integer> intBox = new Notepad<>();
intBox.setMemo(123);
System.out.println(intBox.getMemo()); // 123
}
}
제네릭(Generic)은 클래스, 인터페이스, 메소드를 정의할 때 타입을 일반화하여 다양한 타입을 처리할 수 있도록 하는 기능입니다.
타입 매개변수 (Type Parameter)
타입 매개변수는 제네릭 클래스나 메드에서 사용할 수 있으며, 일반적으로 대문자 한 글자로 표현합니다.
- T Type
- E Element
- K Key
- V Value
주로 위와 같은 형식으로 이름 타입 매개변수는 정해져있는 것이 아닌 사용자가 이름을 마음대로 정할 수 있습니다.
제네릭 클래스 (Generic Class)
// 제네릭 클래스 정의
class Notepad<T> {
...
}
제네릭 클래스는 클래스 정의에서 타입 매개변수를 사용하여 다양한 타입을 처리할 수 있는 클래스를 의미합니다. 제네릭 클래스를 사용하면 클래스 인스턴스를 생성할 때 원하는 타입을 지정할 수 있습니다.
제네릭 클래스의 타입 인자 제한하기
class Notepad<T extends Number>
위에 코드는 제네릭 타입 T를 Number와 Number의 하위 클래스만을 허용하도록 제한하는 상한 바운드 제네릭입니다.
즉 int double 같은 정수 실수 자료형만 인자 전달이 가능하고 String 같은 자료형은 인자 전달을 받을 수 없게 제한합니다.
제네릭 메소드(Generic Method)
class Util {
// 제네릭 메소드 정의
public <T> void prinT(T t) {
System.out.println(t);
}
}
// 제네릭 메소드 사용
public class Main {
public static void main(String[] args) {
Util util = new Util();
util.prinT(3);
util.prinT("Hello");
}
}
제네릭 메소드는 메소드 정의에서 타입 매개변수를 사용하여 다양한 타입을 처리할 수 있는 메소드를 의미합니다. 제네릭 메소드는 클래스가 제네릭 클래스인지와 관계없이 사용할 수 있습니다.
또한 제네릭 메소드는 static 선언 유뮤와 상관 없이 정의가 가능합니다.
주의할 점은 컴파일러에게 제네릭 메소드 인자 T가 무엇인지 알려주어야합니다. 그래서 제네릭 메소드는 void, String 같은 반환형 앞에 <T>라고 선언하여 메소드의 T가 타입 매개변수임을 알려야 합니다.
제네릭 클래스와 다른점은 제네릭 클래스는 인스턴스 생성 시 자료형이 결정된다면 제네릭 메소드는 메소드 호출 시 자료형이 결정됩니다.
와일드카드(Wildcard)
import java.util.List;
public class Main2 {
// 모든 타입의 리스트를 출력
public static void printList(List<?> list) {
for (Object o : list) {
System.out.print(o);
System.out.print(' ');
}
System.out.println();
}
public static void main(String[] args) {
List<Integer> intList = List.of(1, 2, 3);
List<String> strList = List.of("A", "B", "C");
printList(intList); // 1 2 3
printList(strList); // A B C
}
}
제네릭 와일드카드는 자바 제네릭에서 제네릭 타입의 경계를 더 유연하게 지정하기 위해 사용됩니다.
제네릭은 타입간의 캐스팅이 불가능하기 때문에 이를 해결하기 위해서 와일드카드가 사용됩니다.
등장하게된 배경
자바에는 공변성(Covariance)과 반공변성(Contravariance) 둘을 합쳐서 변성(Variance) 이라고 합니다.
그리고 무공변성(불공변성) 또한 존재합니다.
- 공변성 (Covariance) : 공변성은 타입 계층 구조에서 하위 타입이 상위 타입으로 변환될 수 있는 특성을 말합니다.
- 반공변성 (Contravariance) : 반공변성은 타입 계층 구조에서 상위 타입이 하위 타입으로 변환될 수 있는 특성을 말합니다.
- 무공변성(불공변성) : 다른 타입은 받을 수 없고 해당 타입만 받을 수 있는 특성을 말합니다.
객체 타입과 컬렉션 프레임워크 모두 상속 다형성이 존재하여 서로 간의 캐스팅이 가능하지만 제네릭의 경우에는 Object와 Number가 상속 관계를 형성하고 있는 관계라도 제네릭<Object>와 제네릭<Number>는 상속 관계를 형성하지 않는 별개의 자료형입니다.
즉 제네릭은 무공변성입니다.
제네릭 무공변성의 문제
public void a(Object[] arr)
Integer[] arr = {1,2,3};
a(arr);
배열은 공변성이기 때문에 코드에 문제가 없습니다.
하지만 제네릭을 사용하면 Object 와 Integer 간의 타입 캐스팅이 불가능해서 오류가 발생하게 됩니다. 이러한 문제점을 해결하기 위해서 와일드카드라는 것이 등장하게 되었습니다.
결국 와읻드카드는 무엇이든 될 수 있다라는 뜻을 의미합니다.
와일드카드의 제한
public class wildcard {
// 무제한 와일드카드
public static void printList(List<?> list) {
for (Object o : list) {
System.out.println(o);
}
}
// 상한 제한 와일드카드
public static void upList(List<? extends Number> list) {
for (Number n : list) {
System.out.println(n);
}
}
// 하한 제한 와일드카드
public static void downList(List<? super Integer> list) {
for (Object i : list) {
System.out.println(i);
}
}
public static void main(String[] args) {
List<Integer> intList = List.of(1, 2, 3);
printList(intList); // 1 2 3
List<Double> doubleList = List.of(1.1, 2.2, 3.3);
upList(doubleList); // 1.1 2.2 3.3
List<Number> numberList = new ArrayList<>();
numberList.add(1);
numberList.add(2);
numberList.add(3);
downList(numberList);
}
}
무제한 와일드카드
무제한 와일드카드는 모든 타입을 허용하며, 타입의 제약이 없는 제네릭 타입을 처리할 때 사용됩니다. 이는 Object로 변환할 수 있는 모든 타입을 의미합니다.
상한 제한 와일드카드
상한 바운드 와일드카드는 특정 타입의 하위 클래스나 구현체만 허용하도록 제한합니다. 주로 읽기 전용의 데이터를 다룰 때 유용합니다.
하한 제한 와일드카드
하한 바운드 와일드카드는 특정 타입의 상위 클래스만 허용하도록 제한합니다. 주로 쓰기 연산이 필요한 경우에 유용합니다.
출처
W3Schools.com
W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.
www.w3schools.com
'Programming > Java' 카테고리의 다른 글
열거형, 가변인자, 어노테이션 (0) | 2024.08.11 |
---|---|
컬렉션 프레임워크 (0) | 2024.08.10 |
Arrays 클래스 (0) | 2024.08.09 |
StringTokenizer 클래스 (0) | 2024.08.09 |
래퍼 클래스 (0) | 2024.08.09 |