java(36):泛型

日期:2017/11/25


     泛型的使用能够解决处理不同类型数据时遇到的困难。泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

     在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

     泛型的好处是在 编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。


代码例子1:

package com.code.generic_paradigm;
//ArrayList<String> a  ; ArrayList  b
import java.util.ArrayList;

public class test02 {
	public static void main(String[] args){
		ArrayList<String> a = new ArrayList<String>();  
		ArrayList  b = new ArrayList();  
		Class c1 = a.getClass();  
		Class c2 = b.getClass();  
		System.out.println(c1.getClass().getName());
		System.out.println(c2.getClass().getName());
		System.out.println(c1 == c2); //true  
	}
}


代码例子2:


package com.code.generic_paradigm;

class FX<T>{
	private T ob;
	public FX(T ob){
		this.ob = ob ;		
	}
	public T getob(){
		return ob;
	}
	public void showetype(){
		System.out.println("T real parttern is :"+ob.getClass().getName());
	}
}

public class test01 {
	public static void main(String [] args){
		FX<Integer> intob = new FX<Integer>(100) ;
		intob.showetype();
		System.out.println("value="+intob.getob());
		System.out.println("------------------");
		
		FX<String> strob = new FX<String>("mmb");
		strob.showetype();
		System.out.println("value="+strob.getob());
	}

}

输出结果:

T real parttern is :java.lang.Integer
value=100
------------------
T real parttern is :java.lang.String
value=mmb


泛型的好处:

(1)类型安全。 

通过知道使用泛型定义的变量的类型限制,编译器可以更有效地提高Java程序的类型安全。 

(2)消除强制类型转换。 

消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。所有的强制转换都是自动和隐式的。

(3)提高性能。 

[java]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. Lits list1 = new ArrayList();  
  2. list1.add("CSDN_SEU_Cavin ");  
  3. String str1 = (String)list1.get(0);  
[java]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. List<String> list2 = new ArrayList<String>();  
  2. list2.add("CSDN_SEU_Cavin ");  
  3. String str2 = list2.get(0);  

对于上面的两段程序,由于泛型所有工作都在编译器中完成,javac编译出来的字节码是一样的(只是更能确保类型安全),那么何谈性能提升呢?是因为在泛型的实现中,编译器将强制类型转换插入生成的字节码中,但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来了可能。


注意事项

(1)泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。

(2)泛型的类型参数可以有多个。

(3)不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。

 

[java]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. if(ex_num instanceof FX<Number>){   
  2. }  

 

(4)不能创建一个确切的泛型类型的数组。

 

[java]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. List<String>[] lsa = new List<String>[10]; // Not really allowed.    
  2. Object o = lsa;    
  3. Object[] oa = (Object[]) o;    
  4. List<Integer> li = new ArrayList<Integer>();    
  5. li.add(new Integer(3));    
  6. oa[1] = li; // Unsound, but passes run time store check    
  7. String s = lsa[1].get(0); // Run-time error: ClassCastException.    

这种情况下,由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的,所以可以给oa[1]赋上一个ArrayList<Integer>而不会出现异常,但是在取出数据的时候却要做一次类型转换,所以就会出现ClassCastException,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。

下面采用通配符的方式是被允许的:

 

[java]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
    1. List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.    
    2. Object o = lsa;    
    3. Object[] oa = (Object[]) o;    
    4. List<Integer> li = new ArrayList<Integer>();    
    5. li.add(new Integer(3));    
    6. oa[1] = li; // Correct.    
    7. Integer i = (Integer) lsa[1].get(0); // OK  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值