这是我参与更文挑战的第1天,活动详情查看: 更文挑战
Java 泛型的简单使用(一)
同步代码地址 github.com/xyz0z0/Andr…
简单介绍
平时在开发过程中对于 List 系列方法,相比我们是经常使用,在使用过程中我们需要什么类型的 List 都可以,这个就是泛型在帮助我们了。泛型也就是为了这种同一套逻辑的情况下支持不同数据而准备的。
使用的时候很简单,通过<>来定义就可以了。
public class GenericActivity extends AppCompatActivity {
// ①
private final List<String> mNameList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_generic);
mNameList.add("Jack");
// ②
List<String> list = Arrays.asList("Jack", "Joe", "David");
Log.d("GenericActivity", "" + mNameList.size());
Log.d("GenericActivity", "" + list.size());
}
}
上面代码中①部分就是使用泛型类了。既然有了泛型类,那么泛型方法呢?代码②中就是对泛型方法的调用。我们看看 Arrays.asList 方法的定义。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
在 static 和出参类型中通过 声明了方法使用了泛型类型。
自定义泛型类
看完了最基本的使用,让我们试试自定义一个泛型类并使用吧。我们分别定义 Fruit、Apple、ShoppingCart、ShoppingCartUtil 四个类。 购物车类定义成泛型类,接着使用这个类 。
ShoppingCart<Apple> shoppingCart2 = new ShoppingCart<>();
shoppingCart2.buy(new Apple());
ShoppingCartUtil.showSize(shoppingCart2);// error
定义后按照第一步的方法使用并添加一个苹果,可以看到没有问题。但是在我们调用参数为 ShoppingCart 的 showSize 方法时会发现,报错了。编译器提示类型不匹配。
但在我们的定义中 Apple 是 Fruit 的子类,为什么 ShoppingCart 就不能替换成 ShoppingCart 呢?
泛型的限定符
这是因为 Java 泛型中使用的机制是泛型擦除,为了兼容之前版本,在生成的字节码中,我们定义的泛型信息都会被替换成 Object ,在获取的时候,编译器通过添加强制类型转换来保证我们代码的正确性。
那么如果我们在使用中确实需要这种继承关系呢,这时就可以使用通配符来实现。比如这个方法就可以修改一下。
public static void showSize(ShoppingCart<? extends Fruit> list) {
Log.d("sss", "fruit size " + list.size());
}
? extends Fruit 表示我们的泛型类型可以是 Fruit 或子类,这样上一步中的报错问题就解决了。这个叫做泛型上界,在开发过程中是比较常用的。有了上界那么是否有泛型下界呢?答案是有的。定义也很方便,就是将上面的 extends 换成 super ,表示泛型类型可以是 Fruit 或父类。
public static void showSizeSuper(ShoppingCart<? super Fruit> list) {
Log.d("sss", "fruit size " + list.size());
}
泛型下界我在平时开发中使用的就很少了,几乎都是在一些框架中碰到过。上下界问题中又牵扯出一个逆变和协变的问题。这个我们下次再说。
本文是个人的学习记录,不免对技术点有错误或不够深入的理解,还望大神小白批评指教。