为什么使用泛型
- 泛型实质上就是使程序员定义安全的类型,在没有出现泛型之前,Java也提供了对Object的引用“任意化”操作,这种操作就是对Object引用进行向上转型或者向下转型的操作,但某些强制类型转换的错误不会被编译器捕捉,而在运行后出现了异常,可见强制类型转化存在安全隐患,所以提供了泛型机制。
public class OverClass<T> { //定义泛型类
private T over; //定义泛型成员变量
public T getOver(){ //设置getOver方法
return over;
}
public void setOver(T over){ //设置setOver方法
this.over=over;
}
public static void main(String[] args) {
//实例化一个Boolean对象
OverClass<Boolean> over1 = new OverClass<Boolean>();
//实例化一个Float型对象
OverClass<Float> over2 = new OverClass<Float>();
over1.setOver(true); //不需要进行类型转换
over2.setOver(12.3f);
Boolean b = over1.getOver(); //不需要进行类型转换
Float f = over2.getOver();
System.out.println(b);
System.out.println(f);
// TODO Auto-generated method stub
}
}
- 菱形运算符
GenericMemoryCell<Integer> m = new GenericMemoryCell<Integer>(); //这里就很麻烦
GenericMemoryCell<Integer> m = new GenericMemoryCell<>(); //这样就简化了代码,这就是菱形运算符
- 带有限制的通配符
主要作用是在创建一个泛型类对象时限制这个泛型类的类型实现或者继承某个接口或类的子类,可以使用extends 或者 super 来对泛型加以限制。
A<?extends List> a = null;
a = new A<ArrayList>();
a = new A<LinkedList>();
//如果实例化没有实现List接口的泛型对象,编译器就会报错。例如实例化HashMap对象是=时,编译器就会报错
//如果使用A<?> 这种形式实例化对象,则默认表示可以将A指定实例化Object及以下的子类类型
List<String> l1 = new List<String>();
l1.add("成员");
List<?> l2 = new LinkedList<Integer>();
l2.set(0, "成员改变"); //使用通配符声明的名称实例化的对象不能对其加入新的信息,set()方法不能被调用,只能获取或者删除
类型擦除
泛型在很大程度上时Java语言的成分而不是虚拟机中的结构。泛型类可以由编译器通过所谓的泛型擦除过程转变成非泛型类。这样编译器就生成了一种与泛型类同名的原始类。对于泛型的限制
基本类型
基本类型不能作为参数类型。我们必须使用它们的包装类
instanceof检测
instanceof检测和类型转换只是对原始类做的
static语境
在一个泛型类中,static和static域都不可以引用类的类型变量,因为在类型擦除后就不存在了
泛型类型的实例化
不能创建一个泛型类型的实例
T obj = new T(); //右边是非法的
泛型数组对象
不能创建一个泛型数组
T[ ] arr = new T[10]; //右边是非法的
参数化类型数组
参数化类型数组是非法的