JAVA/JAVA
Java | Generic (2) <?> & <T extends Class> & <? super Class>
pathas
2020. 2. 10. 17:14
< ? >
메소드 매개변수의 자료형에 사용되는 제너릭
- < ? extends Object > 의 줄임 표현
- 어떤 자료형의 객체도 매개변수로 받겠다는 의미
- Unbounded WildCard라고 알려져 있음
예제
3개의 List 컬렉션을 생성하고 하나의 정적 메소드로 각각의 값을 출력하는 프로그램 작성
package j200210;
import java.util.*;
public class WildTest {
public static void main(String[] args) {
// List는 인터페이스이기 때문에 ArrayList 생성 후 Upcasting 이용
List<String> list = new ArrayList();
list.add("test1");
list.add("test2");
list.add("test3");
// Integer 자료형 list2 객체 생성
List<Integer> list2 = new ArrayList();
list2.add(1);
list2.add(2);
list2.add(new Integer(3));
// Double형 list3 생성
List<Double> list3 = new ArrayList();
list3.add(10.1);
list3.add(11.2);
list3.add(12.3);
// static 메소드 호출
printData(list);
printData(list2);
printData(list3);
/*
test1 test2 test3
1 2 3
10.1 11.2 12.3
*/
}
// 리스트 출력 메소드
public static void printData(List<?> list) {
for (Object v : list) {
System.out.println(v);
}
}
/*
* public static void printData2(List<Integer> list) { for (Integer v : list) {
* System.out.println(v); } }
*
* public static void printData3(List<Double> list) { for (Double v : list) {
* System.out.println(v); } }
*/
}
< T extends 클래스 >
상속을 이용해서 T의 자료형을 제한함
- 클래스 선언시 사용하며 인스턴스 생성시 특정 클래스를 상속받은 클래스형만
인스턴스 내부에서 사용할 수 있도록 함 - 특정 인터페이스를 구현한 클래스만 사용하려는 경우에도 사용 가능
< ? extends 클래스 >
매개변수의 자료형을 특정 클래스를 상속받은 클래스로만 제한함
예제
extends의 역할은 자료형의 제한으로 동일하기 때문에
< ? extends 클래스 >의 예제만 다룸
package j200210;
import java.util.*;
// Person 상속X 클래스
class Test {
String name;
}
// Person 클래스
class Person {
String name;
}
// Person 상속 Man 클래스
class Man extends Person {
// 생성자
Man(String name) {
this.name = name;
}
// name 반환 메소드
public String toString() {
return name.toString();
}
}
// Person 상속 Woman 클래스
class Woman extends Person {
Woman(String name) {
this.name = name;
}
public String toString() {
return name.toString();
}
}
public class WildExtends {
public static void main(String[] args) {
// Person
List<Person> listP = new ArrayList<Person>();
listP.add(new Person());
printData(listP); // j200210.Person@15db9742
// Man
List<Man> listM = new ArrayList<Man>();
listM.add(new Man("이순신"));
listM.add(new Man("하현우"));
listM.add(new Man("박효신"));
printData(listM); // 이순신 하현우 박효신
// Woman
List<Woman> listW = new ArrayList<Woman>();
listW.add(new Woman("유관순"));
listW.add(new Woman("백예린"));
listW.add(new Woman("박정현"));
printData(listW); // 유관순 백예린 박정현
// Test
List<Test> listT = new ArrayList<Test>();
listT.add(new Test());
// printData(listT); → Person 클래스를 상속받지 않았기 때문에 메소드 호출 불가
}
// Person 클래스와 그 하위 클래스로 생성된 인스턴스만 매개변수로 전달 가능
public static void printData(List<? extends Person> list) {
for (Person obj : list) {
System.out.println(obj);
}
}
}
< ? super 클래스 >
매개변수의 자료형을 특정 클래스와 그 클래스의 상위 클래스로만 제한함
※ super는 T에 사용 불가
예제
위의 예제와 유사하며 extends 대신 super 사용
package j200210.super2;
import java.util.*;
// Person 클래스
class Person {
String name;
// 기본 생성자
Person() {
}
// 생성자 오버로딩
Person(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
// Person 상속 Man 클래스
class Man extends Person {
// 위의 예제와 동일
}
// Person 상속 Woman 클래스
class Woman extends Person {
// 위의 예제와 동일
}
public class WildSuper {
public static void main(String[] args) {
// Person
List<Person> listP = new ArrayList<Person>();
listP.add(new Person("사람"));
listP.add(new Person("인간"));
printData(listP); // 사람 인간
// Man
List<Man> listM = new ArrayList<Man>();
listM.add(new Man("하현우"));
listM.add(new Man("박효신"));
printData(listM); // 하현우 박효신
// Woman
List<Woman> listW = new ArrayList<Woman>();
listW.add(new Woman("백예린"));
listW.add(new Woman("박정현"));
// printData(listW); → Man 클래스의 상위 클래스가 아니기 때문에 메소드 호출 불가
}
// Man 클래스와 그 상위 클래스로 생성된 인스턴스만 매개변수로 전달 가능
public static void printData(List<? super Man> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
}
제너릭의 <?> 사용방법과 extends, super로 <T>와 <?>의 자료형을 제한하는 방법에 대해 알아보았습니다.
<?>는 어떤 자료형도 매개변수로 받을 수 있기 때문에 와일드카드라고도 불리며
필요한 경우에 extends와 super를 사용해서 자료형의 범위를 제한할 수 있습니다.
<T>의 경우에는 extends는 사용가능하지만 super는 사용할 수 없다는 점을 기억해야겠습니다.