물음표를 사용하여 유형 매개변수를 나타내는 와일드카드는 메소드 는 [알 수 없는 유형]의 [유형 제약 조건]을 나타냅니다.
제네릭은 데이터 유형을 매개변수로 정의하며, 사용 시 특정 유형을 지정할 수 있습니다. 그러나 특정 유형을 사용할 때 결정할 수 없는 경우 와일드카드를 사용하여 이를 해결해야 합니다.
추상적으로 말하면 제네릭은 공분산을 지원하지 않기 때문에 제네릭 유형을 공분산으로 만들기 위해 와일드카드가 도입되었습니다.
다음에서는 두 가지 예를 사용하여 와일드카드의 역할을 살펴봅니다.
ArrayList<Object> list_obj = null; ArrayList<String> list_str = new ArrayList<String>(); // ArrayList 的元素支持 String -> Object 的强制转换list_str.add("hello"); System.out.println((Object)list_str.get(0));// 编译错误,泛型不支持协变list_obj = list_str;
코드를 관찰한 결과 다음이 발견되었습니다.
ArrayList에 저장된 요소는 다음과 같습니다. String은 Object의 하위 클래스이기 때문에 String ->에서 Upcast를 지원합니다.
ArrayList의 매개변수 유형이 String -> Object에서 변환될 때 컴파일 오류가 발생했습니다. 제네릭은 공분산을 지원하지 않기 때문입니다.
ArrayList<String> list_str = new ArrayList<String>(); list_str.add("hello"); ArrayList<Integer> list_int = new ArrayList<Integer>(); list_int.add(100); ArrayList<?> list = null; list = list_str; System.out.println(list.get(0)); // hellolist = list_int; System.out.println(list.get(0)); // 100//编译错误list.add("hello"); list.add(100);
를 사용하여 코드를 관찰하고 다음을 찾습니다.
와일드카드를 사용한 후에는 모든 유형의 변환을 허용하여 제네릭이 공분산을 지원하지 않는다는 제한 사항을 해결합니다.
그러나 모든 유형의 개체를 추가할 수 있는 권한도 상실됩니다.
와일드카드에는 세 가지 형태가 있습니다. 즉,
//1、无限定通配符 Demo<?>//2、上边界限定通配符 Demo< ? extends Number> //3、下边界限定通配符 Demo< ? super Number>
다음 예를 살펴보세요. 상속 관계가 있는 세 개의 클래스, 즉 Person ->
class Person{ void print(){ } } class Man extends Person{ void paly(){ } } class Worker extends Man{ void say(){ } }public class Test { public static void main(String[] args) { // 创建了三个 ArrayList 数组 ArrayList<Person> personList = new ArrayList<Person>(); ArrayList<Man> manList= new ArrayList<Man>(); ArrayList<Worker> workerList = new ArrayList<Worker>(); // 限定了上界, ? 代表 Man 以及继承 Man 的类 ArrayList<? extends Man> list = null; list = manList; list = workerList; // 编译错误,因为 Person 是 Man 的父类 list = personList; // 编译错误,因为使用了通配符就不能添加对象 list.add(new Man()); list.add(new Worker()); for(Man man : list){ man.print(); man.paly(); } for(Person per : list){ per.print(); } // 编译错误,因为 ? 也可以代表 Man // 从继承我们可以知道 Worker 肯定是 Man,但 Man 不一定是 Worker。 // for(Worker worker : list); } }
// 省略相同代码...public class Test { public static void main(String[] args) { ArrayList<Person> personList = new ArrayList<Person>(); ArrayList<Man> manList= new ArrayList<Man>(); ArrayList<Worker> workList = new ArrayList<Worker>(); // 限定了下届, ? 代表 Man 以及 Man 的父类 ArrayList<? super Man> list = null; list = personList; list = manList; // 编译错误,因为 Worker 是 Man 的子类 list = workList; // 编译错误,无法确定其父类对象 // Person 继承子 Cell 类,那么用 Person 遍历就是错误的 // for(Man man : list); // for(Person per : list); // 因为 Object 是所有类的根类,所以可以用Object来遍历 // for(Object obj : list); } }
// 省略相同代码...public class Test { public static void main(String[] args) { ArrayList<Person> personList = new ArrayList<Person>(); ArrayList<Man> manList= new ArrayList<Man>(); ArrayList<Worker> workList = new ArrayList<Worker>(); //无边界通配符 ArrayList<?> list = null; //可以代表一切类型 list = personList; list = manList; list = workList; //为了避免类型混淆,只允许使用 Object 遍历 for(Object obj : list); } }
12.Java Basics - Wildcards 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!