泛型,注解--知多少之一(泛型)

来源:互联网 发布:切图用什么软件 编辑:程序博客网 时间:2024/05/16 12:11

   由于时间,今天我们就只说泛型。

 

   泛型是在 jdk 1.5 出现的,那么我们用泛型有什么好处?泛型怎么用?直接看例子,大家估计就能知道答案。(本人喜欢用例子说事(直观,明了),最讨厌枯燥的理论了。呵呵)

 

例1:

 

     目的:该测试是想给 List 集合 digit 放入整数(int)

 

下边这个测试没用泛型:

 

package com.david.geneic;

import java.util.ArrayList;
import java.util.List;

/**
 * 没用泛型的测试
 *
 * 没有明确规定,则可以放 object 型,所以放了 3 种类型
 * 1)int 1,
 * 2) float 1.1
 * 3) String "1.2"
 * 但是这样的话,在遍历该 List 集合会发生什么事?
 * @author David liu
 */
public class Security {
 public static void main(String[] args) {
  List digit = new ArrayList();//在这没用泛型,则其可以放入 Object 型
  
  digit.add(1);
  digit.add(1.1);
  digit.add("1.2");
  
  List<Integer> ll = digit; // List<Integer> ll 一个整型的 List 集合, 然后让它指向  List digit
  
  // 遍历整型 List ll
  for (int d : ll){
   System.out.println(d);
  }
 }
}

 

 

运行结果:

 

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
1
 at com.david.geneic.Security.main(Security.java:20)

 

出现这个结果,想必大家对这个异常不陌生吧, 呵呵。那么我们再看看 用了泛型的例子:

 

下边的测试用了泛型:

 

package com.david.geneic;

import java.util.ArrayList;
import java.util.List;

/**
 * 用了泛型的测试
 *
 * 明确规定,要放入的是整型(int),那么我们再放入以下  3 种类型
 * 1)int 1,
 * 2) float 1.1
 * 3) String "1.2"
 * 但是这样的话,又会发生什么事?
 * @author David liu
 */
public class Security {
 public static void main(String[] args) {
  List<Integer> digit = new ArrayList<Integer>();// 整型的 List digit
  
  digit.add(1);
  digit.add(1.1);
  digit.add("1.2");
  
  // 遍历整型 List ll
  for (int d : digit){
   System.out.println(d);
  }
 }
}

 

此时会报:The method add(Integer) in the type List<Integer> is not applicable for the arguments (double) 和 The method add(Integer) in the type List<Integer> is not applicable for the arguments (String),也就是说如果不放入一个 int 型,就不能编译。这样在编译期间就能检查出来错误,对我们来讲真可谓是福音。呵呵

 

总结:通过 例1 两个测试大家应该知道我们要用泛型的好处:安全性。

 

例2:

 

    目的:解释 List<E> 和 List<String> 的别

 

大家还记得 动态代理--简单实现(地址:http://blog.csdn.net/dreamStronger/archive/2010/09/12/5878425.aspx) 那章中的那个计算速度的接口:

 

/**
 * 计算速度的接口
 * @author David liu
 * @param <E>
 *        此处用到了泛型
 */
public interface SpeedOfList<E> {
 public void iteratorList(List<E> list);
}

 

实现类:

/**
  * 特别说明:这里不止可以是 Long 还可以是一切的对象
  */
 @Override

public class SpeedOfOneList implements SpeedOfList<Long> {

 @Override
 public void iteratorList(List<Long> list) {
 }

}

 

那么如果接口为 List<String> 会是什么样子呢?相信不用写都知道了(我们假设 呵呵)。对就只能是List<String>

 

总结:通过 例2 两个测试可以看出:List<E> 更灵活,可以为任意对象。

 

然而此时,需求发生了变化要让其实现类不仅仅失道接受一种对象的参数,可以是多种如:SpeedOfList 和 SpeedOfOneList 等。这种情况我们该怎么办?

 

例3:

  

   目的:List<?> 与 List<E> 的区别

 

如果单说实现某一对象那么这两种是没什么区别的:都可以是任意对象(仅为个人观点,但觉得差不多。呵呵)。主要区别还是看下边测试。

 

解释 List<?> 中的 ? 为通配符(wildcard)

 

 

package com.david.geneic;

import java.util.ArrayList;
import java.util.List;

import com.dy.dynamicProxy.SpeedOfList;
import com.dy.dynamicProxy.SpeedOfOneList;

/**
 * h() 可以接受 SpeedOfList 及其子类的类型的变量, 而不接受
 * String, Long 等类型
 * @author David liu
 *
 */
public class Test {
 public static void h(List<? extends SpeedOfList<Long>> list){}
 
 public static void main(String[] args) {
  List<SpeedOfOneList> list = new ArrayList<SpeedOfOneList>();
  
  h(list);
 }
}

 

可以正常编译

 

然而

 

package com.david.geneic;

import java.util.ArrayList;
import java.util.List;

import com.dy.dynamicProxy.SpeedOfList;
import com.dy.dynamicProxy.SpeedOfOneList;

/**
 * h() 可以接受 SpeedOfList 及其子类的类型的变量, 而不接受
 * String, Long 等类型
 * @author David liu
 *
 */
public class Test {
 public static void h(List<? extends SpeedOfList<Long>> list){}
 
 public static void main(String[] args) {
  List<Long> list = new ArrayList<Long>();
  
  h(list);
 }
}

 

此时会报:The method h(List<? extends SpeedOfList<Long>>) in the type Test is not applicable for the arguments (List<Long>)  编译不能通过。

 

总结:使用通配符(不包括 List<?> 这种)可以更加灵活,即 可以有多种对象类型参数。

 

至此, 关于泛型就说到这,如果有什么疑问或者建议可以加入 QQ群:107354909(java部落)。大家共同探讨。

 

嗯,好瞌睡,睡了。做个好梦 呵呵

原创粉丝点击