循序渐进理解泛型的通配符

来源:互联网 发布:嵌入式与人工智能关系 编辑:程序博客网 时间:2024/06/06 06:57

一 泛型方法的应用

1 代码示例

import java.util.Vector;public class RandomGenerObject {/** * @param args */public static void main(String[] args) {Vector<Integer> v = new Vector<Integer>();Vector<Object> v1 = new Vector<Object>();//radomMeth(v);             //a处代码radomMeth(v1);}public static void radomMeth(Vector<Object> vector) {vector.add("cjg"); //b处代码vector.add(156);   //c处代码for (Object obj : vector) {System.out.println(obj);}}}

2 运行结果

cjg
156

3 代码解析

  • 在radomMeth()方法中,对于Vector<Object>泛型,实现了可以向该参数中添加任意类型的对象,例如b处代码和c处代码,这是因为任何对象的基类都是Object类型,所以任何类型的对象都可以自动转换成Object类型。
  • 在具体调用radomMeth()方法时,只要传入的参数为Object类型泛型对象,才会正确运行。如果是其他类型的泛型对象,则会编译出错。这是因为参数化类型无继承性特性。如果把a处代码的注释去掉,就会提示编译出错。

 

二 泛型通配符的应用

1 代码示例

import java.util.Vector;public class RandomGener {/** * @param args */public static void main(String[] args) {Vector<Integer> v = new Vector<Integer>();v.add(1);v.add(2);radomMeth(v);Vector<Object> v1 = new Vector<Object>();v1.add("aa");v1.add(2.2);radomMeth(v1);}public static void radomMeth(Vector<?> vector) {// vector.add("1");      //a处代码System.out.println("输出" + vector + "各个成员----------");for (Object obj : vector) {System.out.println(obj);}System.out.println("对象的大小" + vector.size());}}

2 运行结果

输出[1, 2]各个成员----------
1
2
对象的大小2
输出[aa, 2.2]各个成员----------
aa
2.2
对象的大小2

3 代码解析

  • 在radomMeth()方法中,通过“?”标识实现接受任何类型参数的方法,即在具体调用该方法时,传入的对象可以是任意类型,例如Integer类型的对象v和Object类型的对象v1。
  • 在radomMeth()方法中,虽然可以接受任意类型的参数,但是具体接受什么类型只有在具体调用方法时才能确定。因此在调用a处代码时,会编译报错。可是如果调用与参数类型无关的方法size(),则不会编译报错。

 

三 通配符的上限和下限的应用

1 代码示例

import java.util.ArrayList;import java.util.List;public class IntegrationGener {public static void main(String[] args) {List<Number> listNums = new ArrayList<Number>();listNums.add(1);listNums.add(1.23);List<Integer> listInteger = new ArrayList<Integer>();List<? extends Number> listNums2 = listInteger;List<? super Integer> listNums3 = listInteger;listNums3.add(7);listNums3.add(null);System.out.println("listNums3中的元素" + listNums3.get(0));System.out.println("listNums3中的元素个数" + listNums3.size());System.out.println("listNums2中的元素" + listNums2.get(0));System.out.println("listNums2中的元素个数" + listNums2.size());listNums3.add(null);System.out.println("listNums3中的元素个数" + listNums3.size());System.out.println("listNums2中的元素个数" + listNums2.size());List<Number> listNums1 = new ArrayList<Number>();List<? super Integer> listNums4 = listNums1;listNums4.add(6);}}

2 运行结果

listNums3中的元素7
listNums3中的元素个数2
listNums2中的元素7
listNums2中的元素个数2
listNums3中的元素个数3
listNums2中的元素个数3

3 代码解析

  • 为了解决泛型参数类型无继承性,出现了extends和super标识符号。List<? extends Number> listNums2表示listNums2对象可以被Number类型的任何子类型对象(List<Integer> listInteger)赋值。List<? super Integer> listNums3表示listNums3对象可以被Integer类型的任何父类(listNums1)或Interger类型对象(listInteger)赋值。
  • 一条比较通用的原则是,如果要向列表中添加元素则用<? super T>,如果要从列表中获取元素则用<? extends T>,如果既要获取又要添加则不使用通配符。
0 0