转载

java笔记-two-java泛型程序设计(简记)

类型参数: ArrayList<String> files = new ArrayList<>() (String便是类型参数,且构造器中可省去,省去的类型依据变量的类型推断) 泛型类: 具有一个或多个类型变量的类。

public class Pair<T> 
{
	private T first;
	private T second;
	
	public Pair() {first = null;second = null ;}
	public Pair(T first,T second) {this.first = first;this.second = second;}
	public T getFirst() {return first;}
	public T getSecond() {return second ;}
	
	public void setFirst(T newValue) {first = newValue;}
	public void setSecond(T newValue) {second = newValue;}
}
//可以有多个类型变量 :public calss Pair<T,U>{...}(通常事大写的形式)
复制代码

泛型方法:类型变量放在修饰符的后面,返回类型的前面(该方法既可以放在普通类,也可以放在泛型类)

class ArrayAlg
{
	public static <T> T getMiddle(T... a)
    {
    	return a[a.length/2];
    }
}
复制代码

泛型方法的调用:

String middle = ArrayAlg.<String>getMiddle("John","A","Public");
<String>

类型变量限定:保证使用该类型对象的时候调用的方法存在

public static <T extends Comparable> T min(T[] a) 
  {
  	if(a == null || a.length == 0) return null;
  	T smallest = a[0];
  	for(int i = 0 ;i < a.length;i++) 
  	
  		if(smallest.compareTo(a[i]) > 0) smallest = a[i];
  	return smallest;
  	
  	 
  } 
复制代码
extends
T extends Comparable & Serializable

泛型代码和虚拟机:

  • 类型擦除:定义泛型类型的同时提供了相应的原始类型(原始类型的名字便是删去类型参数后的泛型类型名),擦除类型变量,并替换为限定类型(无限定类型的用Object),结果是一个普通的类。
public class Pair
{
	private Object first;
	private Object  second;
	
	public Pair() {first = null;second = null ;}
	public Pair(Object  first,Object  second) {this.first = first;this.second = second;}
	public Object  getFirst() {return first;}
	public Object getSecond() {return second ;}
	
	public void setFirst(Object  newValue) {first = newValue;}
	public void setSecond(Object  newValue) {second = newValue;}
}
复制代码
  • 有限定类型的情况下,选第一个作为原始类型的替换
public  class   Interval<T  extends  Comparable & Serializable >  implements   Serializable
{
	private   T  lower;
	private   T  upper;
    ...
	public Interval(T first,Ts econd)
	{
		if(first.compareTo(second)<=0){lower=first;upper=second;}
		else{lower=second;upper=first;}
	}
}
//原始类型
public class   Interval   implements   Serializable
{
	private    Comparable  lower;
	private    Coiparable   upper;
    ....
	public    Interval(Coiparable  first,Coiparable  second){...}
}
复制代码

为了提高效率,最好将标签接口(没有方法的接口)放在边界末尾 翻译泛型表达式:调用泛型方法,若擦除返回类型,编译器插入强制类型转换 桥方法:为了解决多态与类型擦除的冲突 Java泛型转换的事实:

  • 虚拟机中没有泛型,只有普通的类和方法
  • 所有的类型参数都用它们的限定类型替换。
  • 桥方法被合成来保持多态
  • 为保持类型安全性,必要时插入强制类型转换

约束与局限性:

  • 不能用类型参数代替基本类型;类似的 没有 Pair<double> ,只有 Pair<Double>
  • 运行时类型查询只适用于原始类型,(虚拟机中总有一个特定的非泛型类型,So所有的类型查询只产生原始类型)
  • 不能创建参数化类型的数组(记住,是不能创建 Pair<String>[] T = new Pair<String>[10]; ,声明变量 Pair<String>[] T 还是可以的, 原因:对于泛型类型,即使通过了数组存储检查,还是导致类型错误。
  • Varargs警告(向参数个数可变的方法传递一个泛型类型的实例,也就是说参数可变时,实际创建的时一个参数数组,这时创建的时泛型类型的数组,在这种情况下,不会报错,而是含警告)
  • 不能实例化类型变量,例如 publicPair(){first=newT();second=newT();}//Error (类型擦除将T改变成Object,解决方法: javaSE之后可以让调用者提供构造器表达式,传统的办法是使用 Class.newInstance 构造泛型对象)
  • 不能构造泛型数组
  • 泛型类的静态上下文中类型变量无效(不能在静态域或方法中引用类型变量)
  • 不能抛出或捕获泛型类的实例(在异常规范中使用变量是允许的)
  • 可以消除对受查异常的检查(异常处理回忆:必须为所有受查异常提供一个处理器)
  • 注意擦除后的冲突(要想支持擦除的转换,就需要强行限制一个类或类型变量不能同时成为两个接口类型的子类,而这两个是同一个接口的不同参数化)

泛型类型的继承规则

  • 举个例子, Pair<T>Pair<S> 是没有关系的
  • 永远可以将参数化类型转换为一个原始类型
  • 泛型类可以扩展或实现其他的泛型类
原文  https://juejin.im/post/5cc2eebe6fb9a0324c20c311
正文到此结束
Loading...