Java 泛型编程详解


Technorati 标记: java,泛型,generic

java泛型应用是java核心基础之一,从java 5开始引进泛型。如果你曾经使用过java Collection,那你已经算是接触过泛型了。在java Collection里使用泛型是一件很简单的事情,可泛型还具有很多你意想不到的作用。在深入了解泛型之前,首先来了解一下泛型的一些基本概念与原理。

一、java 泛型引入

java泛型的应用可以提高的代码的复用性,同时泛型提供了类型检查,减少了数据的类型转换,同时保证了类型安全。下面看一下,泛型如何保证了类型安全:
List list = new ArrayList();
list.add("abc");
list.add(new Integer(1)); //可以通过编译
for (Object object : list) {
 System.out.println((String)object);//抛出ClassCastException异常
}
    上面的代码会在运行时抛出ClassCastException,因为它尝试将一个Integer转换为String。接着,来看一下从java5开始,Collection的用法:
List<String> list = new ArrayList<>();
list.add("abc");
//list.add(new Integer(1)); //编译错误
for (String string : list) {
 System.out.println(string);//无需任何强制类型转换
}
    注意到,List的创建增加了类型参数String,因此只能向list添加String类型对象,添加其他对象会抛出编译异常;同样可以注意到,foreach循环不需要再添加任何强制类型转换,也就移除了运行时的ClassCastException异常。
二、泛型的类与接口
    既然是学泛型,自然就要知道如何去使用泛型定义自己的类和接口。同时为了加深理解泛型的作用,先引进一个原始的类:
public class Gen {
 private Object obj;
 
 public Object getObj() {
  return obj;
 }

 public void setObj(Object obj) {
  this.obj = obj;
 }
 
 public static void main(String[] args) {
  Gen gen = new Gen();
  gen.setObj("abc");
  String str = (String) gen.getObj();//类型转换,可能会引起运行时ClassCastException
 }
}
    原始类的定义,容易引发ClassCastException,和第一大点谈到的类似。现在来看一下泛型类来重新定义Gen — 使用<>指定泛型参数,如下:
public class Gen<T> {
 T obj;

 public T getObj() {
  return obj;
 }

 public void setObj(T obj) {
  this.obj = obj;
 }
 public static void main(String[] args) {
  Gen<String> gen = new Gen<>();
  gen.setObj("abc");
//  gen.setObj(10);  //无法通过编译
  String str = gen.getObj(); //无需类型转换
  //-----------------------------
  Gen gen2 = new Gen();//raw type原始类型
  gen2.setObj("abc");
  gen2.setObj(10); //可以通过编译,自动装箱将10转化为Integer对象
  Integer num = (Integer) gen2.getObj();//使用了强制类型转换
 }
}    细心的你会发现在main()方法里是使用泛型类型Gen<String>,便不再需要强制类型转换,也就移除了运行时的ClassCastException。同时为了区别,在此也定义了一个没有使用泛型类型的gen2,这时,编译器会弹出一个警告“Gen is a raw type,References to generic type Gen<T> should be parameterized”。当我们不提供泛型类型时,会默认使用Object会代替,也是因此这样,gen2可以设置String和Integer类型,不过,我们应尽量去避免这种这种情况的出现,如此,便又需要用到强制类型转换,也伴随着运行时的ClassCastException异常。
    tips:可以使用@SuppressWarnings("rawtypes")来抑制编译器弹出警告。
    接口的泛型应用和类的泛型应用很类似,如下:
public interface List <E> {
  void add(E x);
  Iterator<E> iterator();
}

public interface Iterator<E> {
  E next();
  boolean hasNext();
}
    类似的,可以将此应用到自定义的接口与类当中。另外再提一下的是,可以使用多个泛型参数来定义接口与类,比如Map<K,V>;同时,泛型类型也可以作为一个参数来用,如下:new HashMap<String, List<String>>()。

更多详情见请继续阅读下一页的精彩内容

Java 泛型数组 深度解析

Java中泛型之类型通配符(?) 

Java中泛型之类型参数(T) 

什么是Java泛型

Java使用反射来获取泛型信息

利用Java泛型实现简单的泛型方法

  • 1
  • 2
  • 3
  • 4
  • 下一页

相关内容