泛型总结

7. 泛型

泛型(generic)是指参数化类型的能力,泛型的本质也是将数据类型参数化。可以定义泛型类型的类或方法。随后编译器会用具体的类型来替换它。使用泛型的主要优点是能够在编译时,而不是运行时检测出错误,从而提高软件的可靠性和可读性。

泛型类,接口和泛型方法:

<T><E>表示泛型类型(formal generictype),随后可以用一个实际具体类型(concrete type)来替换他。替换泛型类型称为泛型实例化(generic instantiation)。

 

定义一个类为泛型类型,需要将泛型类型放在类名之后。如:public class GenericStack<E> ;

 

泛型类的构造方法应该被定义为publicClassName() ,而不是public ClassName<E>();泛型类多个参数时,可以写成<E1,E2,E3>;

 

泛型方法定义时:修饰符 <E>返回类型方法名(),泛型类型放在方法返回类型之前

如:public static <E extends Comparable<E>>  E max(E a , E b ); 这就是可以将泛型指定为另一种类型的子类型。

调用泛型方法时:需要将实际类型放在尖括号内作为方法名的前缀。如:

Object.<Integer>print(integer);

 

使用类型参数的泛型类型称为原始类型(rawtype)。比如:ArrayList li = new ArrayList()。但是原始类型是不安全的,因为编译阶段没有出错,但是运行阶段有可能会出错。

 

通配符:

ClassName<Integer>并不是ClassName<Number>的子类,为了避免出现这个问题,出现了通配泛型类型。有三种:?、 ? extends T 和 ? super T;

<? Extends Number> 表示的是Number和Number的子类型的通配类型。

 

下面的例子有点意思,两种编译都正确:

public class WildCardDemo3 {
	 public static void main(String[] args) {
		    GenericStack<String> stack1 = new GenericStack<String>();
		    GenericStack<Object> stack2 = new GenericStack<Object>();
		    stack2.push("Java");
		    stack2.push(2);
		    stack1.push("Sun");
		    add(stack1, stack2);
		    WildCardDemo2.print(stack2);
		  }

第一种:
		  public static <T> void add(GenericStack< ? extends T > stack1,
		      GenericStack<T> stack2) {
		    while (!stack1.isEmpty())
		      stack2.push(stack1.pop());
		  }

第二种:		  
		  public static <T> void add(GenericStack< T > stack1,
			      GenericStack<? super T> stack2) {
			    while (!stack1.isEmpty())
			      stack2.push(stack1.pop());
			  }
}


 

消除泛型:

泛型类型使用类型消除(type erasure)的方法来实现。编译器使用泛型类型来编译代码,但是随后消除它。所以泛型在运行时是不可用的。

 

泛型存在于编译阶段,一旦编译器确认泛型类型是安全的,就会将它转换为原始类型。比如:

ArrayList<String>list = new ArrayList<String>();

list.add(“hahah”);

String s= list.get(0);

转换成:

ArrayListlist = new ArrayList();

list.add(“hahah”);

String s= (String)list.get(0);

 

当编译泛型类、接口和方法时,编译器会用Object类型代替泛型类型。

 

如果一个类型是不受限的,那么编译器就会用一个受限类型来替换它。如:

publicstatic <E extends Number> void print();

替换成:

publicstatic <Number> void print();

 

泛型类会出现运行时被消除,需要注意的是:

1.      不管实际的具体类型是什么,泛型类是被他所有的实例所共享的。虽然会创建出不同类型的实例,但运行时只有一个类会被加载到JVM中的。表述如下是错误的:

listinstanceof Object<String>是错误的,因为Java虚拟机中并没有单独存储这个Object<String>类,只有Object类。

2.      不能是有泛型类型来创建实例。 不能使用new E();

3.      不能使用泛型类型来创建数组。如new E[];但是可以通过类型转换来规避这个限制。如:

E[] ll = (E[])new Object[10];这种形式是允许的。

4.      *在静态环境下不允许类的参数是泛型类型。这是由于泛型类的所有实例都有相同的运行时类。所以泛型类的静态变量和方法都是被它的所有实例所共享的。因此在静态方法、数据域或者初始化语句中,为了类而引用泛型类型参数是非法的*

5.      *异常类不能是泛型的*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值