一、什么是泛型
泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
例子:
public static void main(String[] args) {
List a = new ArrayList<String>();
a.add("hello");
a.add(10);
for(int i=0;i<a.size();i++){
String str = (String) a.get(i);
System.out.println(str);
}
}
报错:Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
arrayList可以存任意的类型,存入一个String和一个Integer,再取出来当String类型使用时就会报强制类型转换异常。
如果我们把第一行变成
List<String> a = new ArrayList<String>();
a.add(10); 在编译阶段,编译器发现错误。
List<String> a = new ArrayList<>();
List<Integer> b =new ArrayList<>();
Class classA = a.getClass();
Class classB = b.getClass();
System.out.println(classA.equals(classB));
结果为true。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。泛型的信息不会进入运行期。
二、泛型的使用
泛型类:
/**
* 1、T可以是任意标识,常用的有以下几种
* E - Element (在集合中使用,因为集合中存放的是元素)
* T - Type(Java 类)
* K - Key(键)
* V - Value(值)
* N - Number(数值类型)
* ? - 表示不确定的java类型
* S、U、V - 2nd、3rd、4th types
* 2、实例化泛型类时,必须指定T的类型
*/
public class Person<T> {
//T由外部的T指定
private T key;
public Person(T key) {
this.key = key;
}
public T getKey() {
return key;
}
@Override
public String toString() {
return "key=" + key;
}
}
Person<String> p1 = new Person<>("hello");
Person<Integer> p2 = new Person<>(10);
1、泛型的类型参数只能是引用类型,不能是基本类型。
2、不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
3、不能对确切的泛型类型使用instanceof操作,例如X instanceof Person<Integer>不行。
泛型接口:
public interface Student<T> {
public T fun();
}
public class Demo implements Student<String> {
@Override
public String fun() {
String str = new String("hello");
return str;
}
}
如果未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中。
public class Demo<T> implements Student<T>{
}
1、T传入无数个实参,就形成无数种类型的接口。
2、 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型。
泛型方法:
class X {
public <T> T fun(T t){
return t;
}
};
public class Test{
public static void main(String args[]){
X c = new X(); //实例化X对象
String str = c.fun("hello"); //传递字符串
Integer i = c.fun(10); //传递数字
System.out.println(str); // 通过泛型方法返回泛型类型实例
System.out.println(i); // 通过泛型方法返回泛型类型实例
}
}
1、只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法,<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
2、如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法。静态方法无法访问类上定义的泛型。
public class Person<T> {
public <T> void show(T t){ // T 和类上的T不是一个T
}
}
待续。。。