java通配符之“?”
时间: 作者:走吧走吧
简介泛型类和泛型方法
1 | public class Example<T>{ |
泛型类
上面的类Example就是一个泛型类,它在类名的后面加上< T >,不指定T的类型,却可以在类里面把T当做一个已知的类型来使用。
- 使用1-在声明的时候规定类型
1
Example<String> ex = new Example<String>();
这时会把Example类里面所有的T替换为String。
常使用的例子,List集合的使用。
- 使用2-继承该泛型类
1
2public Ex1 extends Example<Char>(){
}
这时,类Ex1的所有方法(继承的)中的T都是Char型。
这样做的好处
就像一个模板一样,类里面的方法,可以供多个对象来使用。
常使用的例子,java在与数据库交互的时候封装的Dao层父类。
泛型方法
上面的getE方法就是泛型方法。
- 使用
1
Boolean b = ex.getE(true);
这时返回的类型就Boolen型。
通配符?
1 | Object obj = null; |
上面的代码,是正确的。子类的值可以给基类。
但是泛型类型的子类型之间是互不相关的。1
2
3List<Object> objList = new ArrayList<Object>();
List<String> strList = new ArrayList<String>();
objList = strList;
这段代码就会报错。因为strList并不是objList的一个子类。
但是如果是 List< ?> list = null;
list = objList;
list = strList;
这样写就可以。
?就是通配符。
1
2 public void test2(List<?> coll){
}
上面的方法,我们就可以构造不同的泛型子类型当做参数。
List< String>、List< Char> 等都可以。
- List< ?>声明了List中包含的元素类型是未知的。通配符所代表的其实是一组类型,但具体的类型是未知的。List< ?>所声明的就是所有类型都是可以的。但是List< ?>并不等同于objList。objList实际上确定了List中包含的是Object
及其子类,在使用的时候都可以通过Object来进行引用。- List< ?>则其中所包含的元素类型是不确定。其中可能包含的是String,也可能是 Integer。如果它包含了String的话,往里面添加Integer类型的元素就是错误的。正因为类型未知,就不能通过new ArrayList< ?>()的方法来创建一个新的ArrayList对象。因为编译器无法知道具体的类型是什么。但是对于 List< ?>中的元素确总是可以用Object来引用的,因为虽然类型未知,但肯定是Object及其子类。
向上造型一个泛型对象的引用
1 | <? extends XX> |
extends可以理解为小于等于,任意类型要是XX的子类或者是XX。
假设我们有很多箱子,每个箱子里都装有不同的水果,我们需要找到一种方法能够通用的处理任何一箱水果。更通俗的说法,A是B的子类型,我们需要找到一种方法能够将C< A>类型的实例赋给一个C< B>类型的声明。
1
2 List<Apple> apples = new ArrayList<Apple>();
List<? extends Fruit> fruits = apples;
Apple是Fruit的子类型,List< Apple> 是 List< ? extends Fruit> 的子类型。
向下造型一个泛型对象的引用
1 | <? super XX> |
super可以理解为大于等于,任意类型要是XX的父类或者是XX。1
2List<Fruit> fruits = new ArrayList<Fruit>();
List<? super Apple> = fruits;
Apple是Fruit的子类型,List< Fruit> 是 List< ? super Apple> 的父类型。