Java泛型(4)通配符、上限通配符、下限通配符
1.官方文档
2.简介
2.1 通配符与通配符类型定义
List<?> list1;
List<? super Integer> list2;
List<? extends Number> list3;
- 上面代码中的 ? 就是通配符,表示当前未知的泛型实参,该泛型实参由List<?>赋值时推断而来。如果该类型推断失败,该调用报错。如List.add(E),需要推断,而 List.add(null)和List.clear()等则无需类型推断。
- ? super Integer 是通配符类型,限制泛型实参类型为Integer及其父类。
- ? extends Number 是通配符类型,限制泛型实参为Number及子类型。
2.2 应用范围
可用范围 |
泛型形参 | class A<? extends Number>{} |
成员变量 | List<?> mData; | |
局部变量 | Class<?> clazz; | |
函数形参 |
void foo(List<? extends Number> numbers){ } void fun(List<? super Integer> numbers ){ } |
|
返回值 | List<? super Integer> foo() { return null; } | |
禁用范围 | 泛型形参声明 |
class A<? extends Number> {} //error class C<? super Integer> { } //error |
泛型函数调用 | this.<?>foo(2); //error | |
泛型类实例创建 | new B<?>(); |
示例如下:
public class Wildcards {
List<?> mData ; //成员变量
//class A<? extends Number> { } //error
//class B<? super Integer> { } //error
class C <T> { }
public List<? super Integer> foo() { return null; }
public <T> void foo(T t) { }
@Test
public void test1(){
this.<Float>foo(2f);
//this.<?>foo(2); //error
Class<?> clazz; //局部变量
C<?> objB = new C<>() ; //ok
//Object obj = new C<?>(); //error
}
}
2.3 通配符类型父子关系示例图
3.上限通配符
3.1 语法
? extends XXX ,XXX是类型 、接口 或 泛型类型,如
List<? extends Number> list1 //extends 类
List<? extends Serializable> list2 //extends 接口
List<? extends Comparable<Integer>> list3 //extends 泛型接口
注意 :
通配符上限与泛型形参的限定不一样,后者可以指定多个限定,而前者只能指定一个
@Test
public void wildcards_test4(){
class MyNumber extends Number implements Serializable,Comparable<MyNumber>{
@Override public int compareTo(MyNumber o) { return this.intValue() - o.intValue(); }
@Override public int intValue () { return 0; }
@Override public long longValue () { return 0; }
@Override public float floatValue () { return 0; }
@Override public double doubleValue () { return 0; }
}
class MyInteger extends Number{
@Override public int intValue () { return 0; }
@Override public long longValue () { return 0; }
@Override public float floatValue () { return 0; }
@Override public double doubleValue () { return 0; }
}
class MyByte extends Number implements Comparable{ //warning,raw type
@Override public int intValue () { return 0; }
@Override public long longValue () { return 0; }
@Override public float floatValue () { return 0; }
@Override public double doubleValue () { return 0; }
@Override public int compareTo(Object o) { return 1; } //这里意义,与Object比较
}
class MyFloat extends Number implements Comparable<Float>{ //warning,raw type
@Override public int intValue () { return 0; }
@Override public long longValue () { return 0; }
@Override public float floatValue () { return 0; }
@Override public double doubleValue () { return 0; }
@Override public int compareTo(Float o) { return floatValue() > o ? 1 : (floatValue() == 0 ? 0 : -1); }
}
//ArrayList<? extends Number & Serializable> ee; //error
class A <T extends Number & Serializable & Comparable<?>> {} //ok
class B <T extends Number & Serializable & Comparable<T>> {} //ok
class C <T extends Number & Serializable & Comparable > {} //warning,raw type
A<MyNumber> am = new A<>();
//B<String> bm = new B<>(); //error String 不是number
//C<MyInteger> cm = new C<>(); //error,MyInteger没有实现Comparable
C<MyByte> cb = new C<>(); //ok
C<MyFloat> cf = new C<>(); //ok
}
3.2 作用
- 限制泛型实参的必需为xxx及其子类
- 约定 List<? extends Number> 是 List<Integer>的父类,其它泛型类型同理,如Vector<? extends Number>是Vector<Float>父类。
3.3 示例
//Upper Bounded
public void process1(List<? extends Number> list) { //extends 类
for (Number elem : list) { /* */ }
}
@Test
public void test_upper_bounded (){
List<Number> list0 = new ArrayList<Byte>(); //error
List<Number> list1 = new ArrayList<>() ;
List<Integer> list2 = new ArrayList<>() ;
List<? extends Number> list3 = new ArrayList<Byte>();
List<Object> list4 = new ArrayList<>();
List<? extends Number> argument;
List<?> parent;
Object forefather;
argument = list0;
argument = list1;
argument = list4; //error : 泛型实参Object 是 Number父类
process1(list1);
process1(list2);
process1(list3);
process1(list4); //error : 泛型实参Object 是 Number的父类。
parent = argument; parent = list1 ; //...
forefather = parent ; forefather = argument; //...
}
3.4 ? extends 泛型类型
public void process4(List<? extends Comparable<Integer>> list) { //extends 接口
for (Comparable<Integer> s : list){
}
}
public void process5(List<? extends Comparable<?>> list) { //extends 接口
for (Comparable<?> s : list){
}
}
public void process6(List<? extends Comparable> list) { //extends 接口
for (Comparable s : list){
}
}
@Test
public void wildcards_test3(){
}
4. 未限定的通配符
4.1 作用
在定义泛型类型时,如果只用一个?表示泛型实参。这就是未限定通配符.如: List<?> list; 它是其它List<XXX>的父类,是Object的子类。
4.2 示例
public void printList(List<?> list) {
for (Object elem: list)
System.out.print(elem + " ");
System.out.println();
}
@Test
public void wildcards_test5(){
List<Integer> listInt = Arrays.asList(1,2,3);
List<String> listStr = Arrays.asList("a","b","c");
Object obj = listInt;
List<?> list1 = listInt;
List<?> list2 = listStr;
obj = list1;
obj = list2;
printList(listInt);
printList(listStr);
printList(list1 );
printList(list2 );
}
结果
1 2 3
a b c
1 2 3
a b c
4.3 List<?>与List<Object> 区别
List<?>只能add(null),而List<Object>可add(Object及其子类)。
@Test
public void wildcards_test6(){
ArrayList<Integer> tmp = new ArrayList<>();
List<?> list1 = tmp;
List<?> list2 = Arrays.asList(1,2,3);
List<Object> list3 = Arrays.asList("a","b","c");
Object obj1 = list1;
Object obj2 = list3;
tmp.add(1) ; //ok
tmp.add(2) ; //ok
//list1.add(3) ; //error ,incompatible types: int cannot be converted to CAP#1
out.println(ClassLayout.parseInstance(tmp).toPrintable());
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
list1.add(null) ; //ok
//list1 = list3; //ok
out.println(ClassLayout.parseInstance(list1).toPrintable());
list1.clear() ; //ok
list3.add(1) ; //error,运行时错误。UnsupportedOperationException
list3.add(3f) ; //error,运行时错误。UnsupportedOperationException
list3.add(null) ; //error,运行时错误。UnsupportedOperationException
list3.clear() ; //error,运行时错误。UnsupportedOperationException
}
结果:
java.util.ArrayList object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 0d 00 00 00 (00001101 00000000 00000000 00000000) (13)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 57 60 00 20 (01010111 01100000 00000000 00100000) (536895575)
12 4 int AbstractList.modCount 2
16 4 int ArrayList.size 2
20 4 java.lang.Object[] ArrayList.elementData [1, 2, null, null, null, null, null, null, null, null]
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
java.util.ArrayList object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 0d 00 00 00 (00001101 00000000 00000000 00000000) (13)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 57 60 00 20 (01010111 01100000 00000000 00100000) (536895575)
12 4 int AbstractList.modCount 11
16 4 int ArrayList.size 11
20 4 java.lang.Object[] ArrayList.elementData [1, 2, null, null, null, null, null, null, null, null, null, null, null, null, null]
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
java.lang.UnsupportedOperationException
at java.base/java.util.AbstractList.add(AbstractList.java:153)
at java.base/java.util.AbstractList.add(AbstractList.java:111)
at com.example.sjjg.java.generic.Wildcards.wildcards_test6(Wildcards.java:178)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
5.下限通配符
5.1 语法
? super xxx , xxx为类型、接口、泛型类型,如下:
List<? super Integer> list5 = new ArrayList<Number>();
List<? super Number> list6 = new ArrayList<>();
List<? super Object> list7 = new ArrayList<>();
List<? super A<Integer>> list1 = new ArrayList<>();
List<? super A<E> > list2 = new ArrayList<>();
5.2 作用
- 限定泛型实参的类型为xx及其父类。
- 让List<? super Integer> 成为 List<Object>,List<Number>的父类。
5.3 示例
//Lower Bounded
private void foo_lower(List<? super Number> list){
//? super Number 限制传进来的类型一定是 List<Object>,List<Number> 其中 之一
list.add(0) ; //ok
list.add(1f) ; //ok
list.add(2L) ; //ok
list.add(3) ; //ok
list.add("4") ; //error : List<Object>可以add(String),但是List<Number>无法add(String)
list.add(new Object()) ; //error : List<Object>可以add(Object),但是List<Number>无法add(Object)
List<Object> ll = new ArrayList<>();
ll.add("eee");
Integer elem0 = (Integer) list.get(0) ;
int elem1 = (int) list.get(1) ;
Object elem2 = list.get(2) ;
Number elem3 = (Number) list.get(3) ;
out.println(String.format("elem0 = %s,elem1 = %s,elem2 = %s,elem3 = %s",elem0,elem1,elem2,elem3));
}
@Test
public <T> void lower_bounded1(){
List<Integer> list1 = new ArrayList<>();
List<Number> list2 = new ArrayList<>();
List<Object> list3 = new ArrayList<>();
List<String> list4 = new ArrayList<>();
List<? super Integer> list5 = new ArrayList<Number>();//虽然实际new 的是 ArrayList<Number>
List<? super Number> list6 = new ArrayList<>();
List<? super Object> list7 = new ArrayList<>();
List<? extends Number> list8 = new ArrayList<>();
List<?> parent ;
Object forefather ;
List<? super Number> argument ;
argument = new ArrayList<Integer>(); //error : 泛型实参为Integer
argument = new ArrayList<Number>() ;
argument = new ArrayList<Object>() ;
argument = new ArrayList<String>() ; //error : 泛型实参实参为String
argument = new ArrayList<T>() ; //error : T为不确定
argument = list1; //error : 泛型实参为Integer
argument = list2;
argument = list3;
argument = list4; //error : 泛型实参实参为String
argument = list5; //error : 泛型实参实参可能为Integer,list5 = argument; //ok
argument = list6;
argument = list7;
argument = list8; //error : 泛型实参实参为Number及子类。
foo_lower(list1); //error : 泛型实参为integer不是Number及其父类
foo_lower(list2); //ok
foo_lower(list3); //ok
foo_lower(list4); //error : 泛型实参String 不是Number及其父类
foo_lower(list5); //error : ? super Integer 不完全保证是泛型实参是Number,比如Integer就不是
foo_lower(list6); //ok
foo_lower(list7); //ok
foo_lower(list8); //error : ? extends Number 无法保证是泛型实参是Number,比如Float就不是
// List<?> 是List<xxx>父类 Object是所有类父类。
parent = list1 ; parent = list2; /*...*/ parent = list8; //ok
forefather = parent; forefather = list1; /*...*/ forefather = list8; //ok
}
5.4 ? super 泛型类型<T>
@Test
public <E> void lower_bounded2(){
class A <T> { }
List<? super A<Integer>> list1 = new ArrayList<>();
List<? super A<E>> list2 = new ArrayList<>();
}
6.通配符类型提取
6.1 通配符提取
In some cases, the compiler infers the type of a wildcard. For example, a list may be defined as List<?> but, when evaluating an expression, the compiler infers a particular type from the code. This scenario is known as wildcard capture.
带有 ? 的泛型实参由赋值时推断而来。如果该类型推断失败,该调用报错。
?extends Number 确保泛型实参一定是Number及其子类,但无法确定是哪一个子类,示例如下:
private void upper(List<? extends Number> list){
Object obj = list.get(0); //ok get(int) 不需要泛型类型E
list.set(0,100f) ; //error set(int,E) 需要泛型实参
list.remove(0) ; //ok remove(int) 不需要泛型类型E
list.clear() ; //ok clear() 不需要泛型类型E
list.add(0) ; //error add(E) 需要泛型类型E,这里推断失败
list.add(null) ; //ok add(null) 不需要泛型类型E
if(list.contains("aa")){ //ok contains(Object) 不需要泛型类型E
}
}
? super Integer 可以确保推断出来 泛型实参一定是Integer及其父类,示例如下:
private void lower(List<? super Integer> list){
Object obj = list.get(0); //ok get(int) 不需要泛型类型E
list.set(0,1) ; //ok set(int,E) 1,ok
list.set(0,1f) ; //error set(int,E) 1f是对应Float,不是Integer及其父类
list.remove(0) ; //ok remove(int) 不需要泛型类型E
list.clear() ; //ok clear() 不需要泛型类型E
list.add(0) ; //ok add(E) Integer
list.add(null) ; //ok add(null) 需要泛型类型E,这里推断失败
if(list.contains("aa")){ //ok contains(Object) 不需要泛型类型E
}
}
6.2 通配符的help函数
public class WildcardFixed {
void foo(List<?> i) {
fooHelper(i);
}
// Helper method created so that the wildcard can be captured
// through type inference.
private <T> void fooHelper(List<T> l) {
l.set(0, l.get(0));
}
}