JavaEE-16.Java泛型详解

1.泛型概述

  一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。

  即“参数化类型”,首先将类型定义成参数(类似形参),然后在使用时传入具体的类型(类似实参),相当于把类型当参数一样传递。

  泛型对集合类尤其有用,比如ArrayList,下面举一个刘意老师讲的事例:  

 1 //创建集合类
 2 ArrayList array = new ArrayList();
 3 //添加元素
 4 array.add("hello");
 5 array.add("world");
 6 array.add("java");
 7 array.add(10);
 8 //定义迭代器
 9 Iterator it = array.iterator();
10 //遍历
11 while(it.hasNext()){
12     String s = (String)it.next();
13     System.out.println(s);
14 }

上面代码的运行结果肯定会报错,原因也很明显,集合类ArrayList中添加了3个String元素和1个Integer元素,遍历的时候都转换成了String形式。

因为ArrayList可以存放任意类型,所以创建的时候并不会报错,只会有黄色的警告标志。

如果我们在一开始定义的时候就定义好类型,比如ArrayList<String> array,这样一来,添加元素的时候,如果添加Integer类型的元素就会直接报错。

就这是泛型的来由,能让我们更早的发现错误并提前做好预防。

 

2.泛型的使用

 2.1 泛型类

  把泛型定义在类上,该类具有一个或多个类型变量。

  格式:public class 类名<泛型类型1,...>

  注意:1.泛型类型必须是引用类型。2.中括号中可以有几个泛型类型,但一般我们只定义一个。

  下面还是使用刘意老师的实例,首先定义一个最基本的泛型类: 

1 public class ObjectTool<T> {
2     private T obj;
3     public T getObj() {
4         return obj;
5     }
6     public void setObj(T obj) {
7         this.obj = obj;
8     }
9 }

上例中的这个T就相当于我们前面所说的形参,当我们实际使用的时候,可以根据我们的需要定义实际的类型,具体如下:

1 ObjectTool<String> ot = new ObjectTool<String>();
2 ot.setObj(new String("benon"));
3 String s = ot.getObj();
4 System.out.println("姓名是:"+s);
5         
6 ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
7 ot2.setObj(new Integer(27));
8 Integer i = ot2.getObj();
9 System.out.println("年龄是:"+i);

当我们将T定义为String时,此时输入的元素必须是String类型的,同理,T定义为Integer类型时也是一样的道理。

 

2.2 泛型方法

  把泛型定义在方法上

  格式:public < 泛型类型> 返回类型 方法名(泛型类型)

  在泛型未出现之前,我们要输入多个类型的元素是这样的,如下代码: 

 1 //定义工具类
 2 public class ObjectTool{
 3     public void show(String s){
 4         System.out.println(s);
 5     }
 6     public void show(Integer i){
 7         System.out.println(i);
 8     }
 9     public void show(Boolean b){
10         System.out.println(b);
11     }
12 }
13 
14 //定义实例类
15 public class ObjectToolDemo{
16     public static void main(String[] args){
17         ObjectTool ot = new ObjectTool();
18         ot.show("hello");
19         ot.show(100);
20         ot.show(true);
21     }
22 }

如上可见,因为不知道输入的类型会是什么类型,所以工具类的方法需要多次重载,类型越多,重载的方法也越多,代码变的很冗长。

因此,在JDK5版本后出现了泛型,最初的形式如下代码:

 1 //定义工具类
 2 public class ObjectTool<T>{
 3     public void show(T t){
 4         System.out.println(t);
 5     }
 6 }
 7 //定义实例类
 8 public class ObjectToolDemo【
 9     public static void main(String[] args){
10         ObjectTool<String> ot1 = new ObjectTool<String>();
11         ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
12         ObjectTool<Boolean> ot3 = new ObjectTool<Boolean>();
13 
14         ot1.show("hello");
15         ot2.show(100);
16         ot3.shwo(true);
17     }
18 }

上面的代码中,工具类变的简单了,但实例类却重复代码过多,且工具类也必须定义为泛型类,因此我们又想到了下面更简便的方法:

 1 //定义工具类,该类不是泛型的,而是将泛型定义在方法上
 2 public class ObjectTool {
 3     public <T> void show(T t) {
 4         System.out.println(t);
 5     }
 6 }
 7 
 8 //定义实例类
 9 public class ObjectToolDemo {
10     public static void main(String[] args) {
11         ObjectTool ot = new ObjectTool();
12         
13         ot.show("hello");
14         ot.show(100);
15         ot.show(true);
16     }
17 }

由上面的代码可看出,因为泛型在方法上,show()方法接受的参数是什么类型,输出的结果就会是什么类型,这样一来,方法就可以接受任意类型。

 

2.3 泛型接口

  把泛型定义在接口上

  格式:public interface 接口名 <泛型类型1,...>

  首先,定义一个泛型接口,如下代码:

1 public interface Inter<T> {
2     public abstract void show(T t);
3 }

  其次,当实现接口的类,未传入泛型实参时,如下代码: 

1 public class InterImpl<T> implements Inter<T>{
2     @Override
3     public void show(T t) {
4         // TODO 自动生成的方法存根
5         System.out.println(t);
6     }    
7 }

  最后,当实现接口的类,传入泛型实参时,如下代码:

1 public class InterDemo {
2     public static void main(String[] args) {
3         Inter<String> i = new InterImpl<String>();
4         Inter<Integer> ii = new InterImpl<Integer>();
5         
6         i.show("hello");
7         ii.show(100);
8     }
9 }

 

 3. 泛型通配符 

 1 //定义一个父类和两个子类
 2 class Animal{
 3     
 4 }
 5 class Dog extends Animal{
 6     
 7 }
 8 class Cat extends Animal{
 9     
10 }

  3.1 无界通配符

    ?:任意类型,如果没有明确,那么就是Object以及任意的Java类

        Collection<?> c2 = new ArrayList<Object>();
        Collection<?> c3 = new ArrayList<Animal>();
        Collection<?> c4 = new ArrayList<Dog>();
        Collection<?> c5 = new ArrayList<Cat>();

  3.2 上界通配符

    ? extends E:向下限定,E及其子类

    Collection<? extends Animal> c6 = new ArrayList<Animal>();
    Collection<? extends Animal> c7 = new ArrayList<Dog>();
    Collection<? extends Animal> c8 = new ArrayList<Cat>();

  3.3 下界通配符

    ? super E:向上限定,E及其父类

    Collection<? super Animal> c9 = new ArrayList<Animal>();
    Collection<? super Dog> c10 = new ArrayList<Animal>();
    Collection<? super Cat> c11 = new ArrayList<Animal>();

 

 

posted @ 2020-04-25 16:52  benon  阅读(190)  评论(0)    收藏  举报