JAVA 泛型

概述

集合是可以存放 任意 类型的对象,把对象存储到集合后,那么这时他们都会被 提升成 Object 类型。

当我们在 取出 每一个对象,并且进行相应的操作,这时必须采用 类型转换。

例子:
遍历list中元素的长度

public class GenericDemo {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc");
        list.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放
        for(int i=0,len=list.size;i<size;i++)
            //需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
            String str = (String) list.get(i);
            System.out.println(str.length());
        }
    }
}

抛出异常:java.lang.ClassCastException

报错原因: 由于集合中什么类型的元素都可以存储

解决问题: 在JDK5之后,新增了 泛型(Generic)

泛型(Generics)

可以在 类 或 方法 中 限制类型

当没有指定泛型时,默认类型为 Object类型

好处

  • 限制类型。将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
  • 不需要 类型强转

在集合中使用泛型

作用:

  • 限制放数据的类型

  • 取值时不需要 类型强转

例子:

List<String> list = new ArrayList<String>();

list.add("abc");
list.add("itcast");
// list.add(5);//当集合明确类型后,存放类型不一致就会编译报错
for(int i=0,len=list.size;i<size;i++)
    String str = list.get(i);//不需要强转
    System.out.println(str.length());
}

jdk7以后

在JDK 7后,右侧泛型的尖括号之内可以留空,但是<>仍然要写。简化格式:

ArrayList<String> list = new ArrayList<>();

理解

在类中使用泛型

表示 属性的类型、方法形参类型、方法返回值类型

格式

修饰符 class 类名<代表泛型的变量> {  }

例子:

API中的ArrayList集合:

class ArrayList<E>{ 
    public boolean add(E e){ }

    public E get(int index){ }
       ....
}

符号<E>的含义

这里的<E> ,表示一种指定的数据类型,叫做泛型。 E 取自Element(元素)的首字母。

在构造ArrayList对象时, <E>指定了什么数据类型,那么 add(E e) 方法中,只能添加什么数据类型的对象。

符号<T>的含义

泛型有时也用到<T>,T 取自 Type的首字母,表示传输参数的类型。
用法与 <E> 相同

创建对象的时候指定泛型

例如:ArrayList<String> list = new ArrayList<String>();

此时,变量E的值就是String类型,那么我们的类型就可以理解为:

例子

public class MyGenericMethod<T> {

    public void show(T t) {
        System.out.println(t);
    }


    public static void main(String[] args) {
        //创建对象时,指定泛型
        MyGenericMethod<Student> m=new MyGenericMethod();
        Student std=new Student();
        m.show(std);
    }
}

Student为演示类,空类

在方法中使用泛型

格式

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){

}

例如:

public class MyGenericMethod {
    //方法上的```<T>``` 代表要用到泛型参数
    public <T> void show(T t) {
        System.out.println(t);
    }


    public static void main(String[] args) {
        MyGenericMethod m=new MyGenericMethod();
        Student std=new Student();
        //调用方法时,确定泛型的类型
        m.show(std);
    }
}

Student类为演示类,空类

方法上的<T> 代表括号里面要用到泛型参数(在类名后没定义泛型,此处必须定义泛型)

调用方法时,确定泛型的类型

在接口中使用泛型

格式

修饰符 interface 接口名 <代表泛型的变量> {

}

例如:

public interface MyGenericInterface<E>{
    public abstract void add(E e);

    public abstract E getE();  
}

使用格式:

1、定义类时确定泛型的类型

例如

public class MyImp1 implements MyGenericInterface<String> {
    @Override
    public void add(String e) {
        // 省略...
    }

    @Override
    public String getE() {
        return null;
    }
}

此时,泛型E的值就是String类型。

2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型

例如

public class MyImp2<E> implements MyGenericInterface<E> {
    @Override
    public void add(E e) {
            // 省略...
    }

    @Override
    public E getE() {
        return null;
    }
}

确定泛型:

/*
 * 使用
 */
public class GenericInterface {
    public static void main(String[] args) {
        MyImp2<String>  my = new MyImp2<String>();  
        my.add("aa");
    }
}

原文出处:/show_1EF4sIXmk2JN.html