Java泛型中的标记符含义:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
● ? 通配符类型
● <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
● <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
? 通配符类型示例
类型通配符就是一个问号,将一个问号作为类型实参传给list集合,写作List<?>就可以。这种语法的意思是:List<?>是一个元素类型未知的list,然后list中add()的元素类型可以匹配任何类型。
<span style="font-size:14px;">public void test(List<?> list) { for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } public static void main(String[] args) { Test test = new Test(); </span>List<String> list = new ArrayList<String>();
<span style="font-size:14px;"> list.add("s"); test.test(list); } </span>
在Java集合框架中,对于参数值是未知类型(即使用“?”通配符)的容器类,只能读取其中元素,不能向其中添加元素, 因为,其类型是未知,所以编译器无法识别添加元素的类型和容器的类型是否兼容,唯一的例外是NULL
示例:
public static void main(String[] args) { List<? super test> fruits = null; test test = new test(); List<?> list = new ArrayList(); list.add("z"); //这里添加数据,无法添加成功 test.test(list); } public void test(List<?> list) { for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } }如上面的代码,添加数据是无法添加成功的。如果要添加数据,则必须这样写:
<span style="font-size:14px;"> </span>List<String> list = new ArrayList<String>();
在定义泛型类别时,预设可以使用任何的类型来实例化泛型类型中的类型。
但是如果想限制使用泛型类别时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口,也可以是这个类或接口本身。
<span style="font-size:14px;">import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; public class ListGenericFoo<T extends List> { private T[] fooArray; public T[] getFooArray() { return fooArray; } public void setFooArray(T[] fooArray) { this.fooArray = fooArray; } public static void main(String[] args) { ListGenericFoo<LinkedList> foo1 = new ListGenericFoo<LinkedList>(); ListGenericFoo<ArrayList> foo2 = new ListGenericFoo<ArrayList>(); //Error: Bound mismatch //ListGenericFoo<HashMap> foo3 = new ListGenericFoo<HashMap>(); LinkedList[] linkedLists = new LinkedList[10]; foo1.setFooArray(linkedLists); ArrayList[] arrayLists = new ArrayList[10]; foo2.setFooArray(arrayLists); } }</span>
通配符下限:<? super B>
List<? super B> list = new ArrayList<A>();
这样定义一个list的时候,允许向这个list添加对象。list可以接受其B类型和B的父类。像list中添加对象的时候编译器能确定确切类型。也可以这样理解:Fruit是Apple的父类,也是orange的父类。我们可以说Apple就是一个Fruit。
<span style="font-size:14px;">import java.util.ArrayList; import java.util.List; class A{} class B extends A implements F{} class C extends A{} class D extends A{} class E{} interface F{} public class Test{ public void b(List<? super B> list){ list.add(new B()); ////编译通过 //list.add(new A()); //编译不能通过,要使用类型转换 list.add((B) new A()); ////编译通过 } public static void main(String[] args) { List<? super B> listA = new ArrayList<A>(); test.b(listA); } }</span>
extends 可用于的返回类型限定,不能用于参数类型限定。
super 可用于参数类型限定,不能用于返回类型限定。
带有super超类型限定的通配符可以向泛型对易用写入,带有extends子类型限定的通配符可以向泛型对象读取。——《Core Java》