泛型:

1、使用泛型的目的:

编译器自动帮我们检查,避免向集合中插入错误类型的对象,减少强制转换,确保类型安全,从而使得程序具有更好的安全性和可读性。

2、泛型的实现原理

伪泛型

编译期间,所有的泛型信息都会被擦除,变成(原始类型),所以java的泛型被称为“伪泛型”。

原始类型是什么?

原始类型就是泛型擦除泛型信息后,在字节码中真正的类型,定义一个泛型,相应的原始类型就会被自动提供,原始类型的名字就是去掉参数类型后泛型类型的类名

 

 

泛型的使用

泛型类型来替代原始类型,比如使用T, E or K,V等被广泛认可的类型占位符

泛型的参数可以指定可以不指定

指定:方法中的所有参数类型必须是该泛型类型或者其子类,注意:必须是引用类型

不指定:泛型类型是几种参数类型的共同父类的最小级,直到Object

  1. public static <T> T add(T x,T y){    
  2. return y;    
  3. }   

 

main方法中调用add(String str , int  a)---------返回 ?类型

泛型是如何进行类型判断的??

如何保证我们只能使用泛型变量限定的类型的?

java编译器:先检查代码中泛型的类型,进行类型擦除,再进行编译。

  1. /泛型类型  
  2. class Pair<T> {    
  3. private T value;    
  4. public T getValue() {    
  5. return value;    
  6. }    
  7. public void setValue(T  value) {    
  8. this.value = value;    
  9. }    
  10. }  

擦除getValue()的返回类型后将返回Object类型,编译器自动插入Integer的强制类型转换。也就是说,编译器把这个方法调用翻译为两条字节码指令

1、对原始方法Pair.getValue的调用

2、将返回的Object类型强制转换为Integer

所以说:java的泛型是在编译器层次实现的;

问题集:

ArrayList<String> arrayList1=new ArrayList<Object>();//编译错误 ClassCastException 

ArrayList<Object> arrayList1=new ArrayList<String>();//编译错误

 泛型出现的原因,就是为了解决类型转换的问题 ,违背初衷,不允许

 

泛型类中的静态方法和静态变量不可以使用泛型类所声明的泛型类型参数

泛型参数的实例化是在定义泛型对象指定的

  1. public class Test2<T> {      
  2. public static T one;   //编译错误      
  3. public static  T show(T one){ //编译错误      
  4. return null;      
  5. }      
  6. }    

但是下面的这种情况是可以的:

  1. public class Test2<T> {      
  2. public static <T >T show(T one){//这是正确的      泛型方法使用参数中的T
  3. return null;      
  4. }      
  5. }