说在前头的话:如果迷茫,请做好当下的事!
上一篇讲了泛型的基本知识,如果你没用看过,请参考Java基础之——泛型(一)这篇我们来讲一下泛型高级之通配符吧!
一、通配符是个什么玩意
简单来说,通配符就是一个 ?,用来代表任意类型。例如:
ArrayList<?> arrayList = new ArrayList<String>();
二、通配符的三种形式
- ?
- ? extends E
- ? super E
第一种 ? 代表 任意类型
比如
//这里的arrayList可以接受任意类型
ArrayList<?> arrayList = new ArrayList<String>();
ArrayList<?> arrayList = new ArrayList<Integer>();
注意,有人可能会说,既然是任意类型,能不能用Object来代替,例如
//错误用法
ArrayList<Object> arrayList = new ArrayList<String>();
这是错误的,因为Java在定义泛型时必须要求 前后一致,如果前面是Object,后面必须是Object,
//正确用法
ArrayList<Object> arrayList = new ArrayList<Object>()
//或者
ArrayList<Object> arrayList = new ArrayList<>();
//Java1.7之后,后面的类型可以不用写,你前面传的啥类型,后面默认就是啥类型
那如果我们想接受任意类型怎么办,java已经替我们想好了,就用 ? 来代替就好了。
第二种 ? extends E 代表 E及其子类
比如
public class Genericity {
public static void main(String[] args) {
//这里的类型是Person类,即本身
ArrayList<? extends Person> array1 = new ArrayList<Person>();
//这里的类型 是 Student 类,Persion子类
ArrayList<? extends Person> array2 = new ArrayList<Student>();
//报错,因为只能接受 Person本身 或者他的子类
ArrayList<? extends Person> array3 = new ArrayList<String>();
}
//新建一个person,作为父类,
class Person{
}
//新建一个person,作为子类
class Student extends Person{
}
}
上面的代码非常简单,我们新建了一个Genericity类,然后再里面又新建了两个内部类,Person(父类)和Student(子类),这里
ArrayList<? extends Person> array1 = new ArrayList<Person>();
? extends Person 的意思就是 只能接受Person类(本身)或者它的子类,其他的类型我不接受。
第三种 ? super E 代表 E及其父类
如果看懂了第二种,第三种也很简单,其实是一模一样的
ArrayList<? super Person> array4 = new ArrayList<Person>();
? super Person 的意思就是 只能接受Person类(本身)或者他的父类,其他的类型我不接受。
下面这种接收的就是它的父类(因为任何类都继承于ObJect)
ArrayList<? super Person> array5 = new ArrayList<Object>();
好了,知识点就这么多,不能总是纸上谈兵,让我们来学以致用吧!
三、实践是最好的老师
1.实践一 通过泛型来简化findViewById
在做安卓开发的时候,我们是不是经常写findViewById了吧,每次都要Cast一下
Button btn = (Button)findViewById(R.id.btn);
写多了,都有想吐的感觉了,那怎么办呢?
1.可以用注解的方式(ps我没学)
2.用泛型(就是你了)
3….
在BaseActivity(基类)定义如下泛型方法:
public class BaseActivity extends Activity {
//在这个类中定义泛型方法,以后我们写的类都继承BaseActivity,这样就能调用这个方法
public final <E extends View> E getView (int id) {
try {
return (E) findViewById(id);
} catch (ClassCastException ex) {
Log.e(TAG, “Could not cast View to concrete class.”, ex);
throw ex;
}
}
}
以上的代码很简单,定义了一个getView方法,返回值是E,也就是是说,调用的时候是什么类型,就返回什么类型,接收类型只能是View及其子类,
使用如下
TextView textView = getView(R.id.textview);
Button button = getView(R.id.button);
ImageView image = getView(R.id.imageview);
是不是感觉很简单,如果想学习更多用法,请参考这篇文章通过泛型来简化findViewById
2.实践二 Android之万能的适配器
这里面也用到泛型,参考这篇博客,张鸿洋大神 万能的适配器
如果不是很懂,可以看他的万能适配器 视频
因为有视频讲解,所以就不多说了!可以自己去分析里面的泛型。
好了,就到这里,have a nice day