Java泛型简述

从jdk1.5开始,java 允许定义泛型类,泛型接口,泛型方法. Java AP中的一些接口和类广泛使用了泛型,比如
java.lang.Comparable接口被定义为Comparable< T >泛型接口

什么是泛型

在编码的阶段我们程序员可以使用一些特定的字符(E, T, V)来代替类的属性类型,方法的参数类型,方法返回值类型…等等;随后在编译器阶段,会使用具体的类型来替换它
例子:

public class UsingGenericType<T> {
    
    
	// 定义一个泛型属性
	private T a;
	
	// 定义泛型参数
	public void setA(T a){
    
    
		this.a = a;
	} 
	
	public T getA(){
    
    
		return this.a;
	}

	public static void main(String[] args){
    
    
		// 实例化泛型类(用具体的类型代替泛型)
		UsingGenericType<Integer> ugt = new UsingGenericType();
	}
}

泛型有什么用

使用泛型的主要优点是能够在编译时而不是运行时发现错误; 泛型类或者方法允许程序员指定可以与这些类或者方法一起工作的类型对象. 如果试图使用一个不相容的对象,编译器就会检测出这个错误. 使用泛型能够提高代码的可读性,提高软件的可靠性,可维护性. 使用泛型在某些工作上可以大大减少我们的工作量.即安全又高效

定义泛型类和泛型接口

泛型声明在类名之后,可以用通配符来指定泛型的范围

//为类或者接口定义泛型,当使用时必须指定具体的类型
public class GenericStack<T>{
    
    
	//这里是使用GenericStack声明的泛型T, 而不是另外声明的泛型T
	private ArrayList<T> list = new ArrayList();
}

public interface Readable <T>{
    
    }
// 当使用时必须指定具体的类型
public class PersonInfo implements Readable<Integer>{
    
    }
泛型方法

泛型声明在方法返回值之前,可以用通配符来指定泛型的范围

public class Anonymous{
    
    
	public <T> void test(T t){
    
    
		//业务逻辑
	}
}

//使用 由于T为非受限通配符,可以使用任意类型, 
//这里可以使用1 (int)的原因是编译器做了自动装包int转换成Integer
public static void main(String[] args){
    
    
	new Anonymous.test(1);
}

泛型的通配

可以使用非受限通配,受限通配,下限通配来对一个泛型类型指定范围
非受限通配: 表示具体的类型可以是任意类型

//定义类泛型,在使用时T可以具体为任意类型,即为非受限类型
public class Anonymous<T>{
    
    }

受限通配符:表示该泛型只能由具体的类型的子类或者本身"具现化"

// extends Number:表示T必须是继承Number类.即代替T时,只能使用Number或者Number的子类
public class Anonymous<T extends Number> {
    
    }

下限通配: 表示该泛型只能由具体的类型的父类或者本身 “具现化”

// super Integer: 表示T必须是Integer的父类或者本身
public class Anonymous< T super Integer> {
    
    }

泛型方法声明类似

类型擦除

泛型实现的原理: 类型擦除
泛型相关的信息可以被编译器使用,而在运行时不可用,这被称为类型擦除
泛型存在于编译时.当编译器确认泛型是安全的,就会将它转换成原生类型
例如:

ArrayList<String> list = new ArrayList();
list.add("mango");
String fruit = list.get(0);

//运行时的实际代码
ArrayList list = new ArrayList();
list.add("mango");
String fruit = (String) list.get(0);
// 所以运行时是不知道的泛型信息的

还有一点,不管实际的具体类型是什么,泛型类型是被它所有的实例所共享的.
ArrayList< String> list = new ArrayList();
ArrayList< Integer> list2 = new ArrayList();
尽管在编译时ArrayList< String>和ArrayList< Integer>是两种类型,但是在运行时,只有一个ArrayList 加载到JVM中
System.out.println(list instanceof ArrayList); //true
System.out.println(list2 instanceof ArrayList); // true

泛型使用限制

  1. 不能使用new E() 实例化对象
  2. 不能使用new E[] 实例化数组
  3. 在静态上下文中不允许类的参数是泛型类型
  4. 异常类型不能是泛型
  5. 泛型的具体类型必须是引用类型,不能使用int,char…之类的基本类型

猜你喜欢

转载自blog.csdn.net/qq_29757633/article/details/108137706