public class GenericTest {
public static void main(String[] args) {
ObjectPrinter obejctPrinter = new ObjectPrinter();
Powder powder = new Powder();
obejctPrinter.setMaterial(powder); // Powder -> Object (형 변환)
Powder p = (Powder)obejctPrinter.getMaterial();
Plastic plastic = new Plastic();
obejctPrinter.setMaterial(plastic); // Plastic -> Object (형 변환)
p = (Powder)obejctPrinter.getMaterial(); // 컴파일 단계에서 에러 검출이 되지 않으나 런타임 에러 발생
GenericPrinter<Powder> genericPrinter = new GenericPrinter();
genericPrinter.setMaterial(powder);
p = genericPrinter.getMaterial();
genericPrinter.setMaterial(plastic); // 컴파일 단계에서 에러 검출
}
}
class ObjectPrinter{
private Object material;
public void setMaterial(Object material) {
this.material = material;
}
public Object getMaterial() {
return material;
}
}
class GenericPrinter<T>{
private T material;
public void setMaterial(T material) {
this.material = material;
}
public T getMaterial() {
return material;
}
}
class Powder{ ... }
class Plastic{ ... }
public static <T> T genericMethod(T param) { return param; }
public class GenericPrinter<T>{
static T material; // 컴파일 에러
static T getMaterial(T material) { // 컴파일 에러
return material;
}
static <T> T getMaterial(T material) {
return material;
}
}
<T extends S> // T는 S와 S의 자식 타입이 가능하며 T의 타입을 참조할 수 있습니다.
<? extends S> // S와 S의 자식 타입이 가능합니다.
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
List<String> list2 = new ArrayList<>(Arrays.asList("1", "2", "3"));
testMethod1(list);
testMethod1(list2); // 컴파일 에러
}
public static <T extends Number> void testMethod1(List<T> list) {
T element = list.get(0);
}
public static void testMethod2(List<? extends Number> list) {
Number element = list.get(0);
}
<?> // 모든 타입 가능합니다. <? extends Object>와 같은 의미입니다.
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
testMethod1(list);
testMethod2(list); // 컴파일 에러
testMethod3(list);
}
public static <T> void testMethod1(List<T> list) {
list.add(list.get(0));
}
public static void testMethod2(List<Object> list) {
list.add(list.get(0));
}
public static void testMethod3(List<? > list) {
list.add(list.get(0));
}
<T super S> // 불가능한 타입입니다.
<? super S> // S와 S의 부모 타입이 가능합니다.
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Object> list2 = new ArrayList<>(Arrays.asList(1, 2, 3));
testMethod1(list);
testMethod2(list); // 컴파일 에러
testMethod2(list2);
}
// 상한제한
public static void testMethod1(List<? extends Number> list) {
Number element = list.get(0);
Number n = new Integer(1);
list.add(n); // 컴파일 에러
}
// 하한제한
public static void testMethod2(List<? super Number> list) {
Object element = list.get(0);
Number n = new Integer(1);
list.add(n);
}
class TestClass<T super Number> {
T item;
}
public static <T super Number> void testMethod(List<T> list) {
T item;
}
// Collections 클래스의 sort 메소드입니다.
public static <T extends Comparable<? super T>> void sort(List<T> list) {...}
class Powder implements Comparable<Powder>{
@Override
public int compareTo(Powder o) { ... };
}
class SortClass {
public static <T extends Comparable<T>> void sort(List<T> list){ ... }
public static <T extends Comparable<? super T>> void sort2(List<T> list){ ... }
}
class Material { ... }
class Powder extends Material implements Comparable<Material>{
@Override
public int compareTo(Material o) { ... }
}
public static void main(String[] args) {
List<Powder> list = new ArrayList<>();
SortClass.sort1(list); // 컴파일 에러
SortClass.sort2(list);
}
자바 제네릭(Generics) 기초 https://tecoble.techcourse.co.kr/post/2020-11-09-generics-basic/
자바 [JAVA] - 제네릭(Generic)의 이해 https://st-lab.tistory.com/153
[Java] 제네릭 메소드(Generic Method)란? https://devlog-wjdrbs96.tistory.com/201
제네릭이란? https://vvshinevv.tistory.com/54
제네릭에서 T super ... 사용이 불가능한 이유 Generic-Type Erasure https://velog.io/@sunaookamisiroko/%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%97%90%EC%84%9C-super-%EC%82%AC%EC%9A%A9%EC%9D%B4-%EB%B6%88%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%9D%B4%EC%9C%A0-Generic-Type-Erasure