Generics泛型的应用

Generics泛型的应用

                                      

JDK 5 中的泛型

 

Generics(泛型)

泛型的第一个优点是实现编译时期检查;第二个优点是在使用collection框架的时候不需要cast了。

 

一、先来了解一下JDK5以前是怎么处理的。

JDK5之前的Collection框架以Object为参数,这样整个Collection框架可以变得通用,而不是对于每个数据类型都定义一个Collection

 

比如,Listadd方法: public boolean add(java.lang.Object element)

但是当你使用的时候,get()方法是这样声明的:

public java.lang.Object get(int index)

  throws IndexOutOfBoundsException

请看下面的例子:

List stringList1 = new ArrayList();

stringList1.add("Java 5");

stringList1.add("with generics");

String s1 = (String) stringList1.get(0);

 

一切看起来ok,但是如果这样

List stringList1 = new ArrayList();

stringList1.add("Java 5");

stringList1.add(new Date());

stringList1.add("with generics");

String s1 = (String) stringList1.get(1);

看起来也ok,运行起来就出现

java.lang.ClassCastException: java.util.Date

 

二、应用泛型

正如方法可以接收参数,泛型类型也可以接收参数,这也是为什么generic type也称作 “parameterized type”。用<>angle bracket)将参数传递给泛型。

 

例如:java.util.List,可以写作  List<E> myList,其中E称作类型变量。在JDK5中可以如下实例化:

List<String> myList = new ArrayList<String>();

 

JDK5中,代码可以如下:

           List<String> stringList2 = new ArrayList<String>();

           stringList2.add("Java 5.0");

           stringList2.add("with generics");

           // no need for type casting

           String s2 = stringList2.get(0);

           System.out.println(s2.toUpperCase());

如果你尝试将Date()加入这个List

           List<String> stringList2 = new ArrayList<String>();

           stringList2.add("Java 5.0");

           stringList2.add("with generics");

           stringList2.add(new Date());

           // no need for type casting

           String s2 = stringList2.get(0);

           System.out.println(s2.toUpperCase());

 

系统会提示:

The method add(String) in the type List<String> is not applicable for the arguments (Date)

 

比较前面JDK5之前的处理,已经实现了编译期检查,不会将错误留到运行时候。

 

三、比较JDK5和之前的处理

import java.util.List;

import java.util.ArrayList;

 

public class GenericListTest {

  public static void main(String[] args) {

    // in JDK 1.4

    List stringList1 = new ArrayList();

    stringList1.add("Java 1.0 - 5.0");

    stringList1.add("without generics");

    // cast to java.lang.String

    String s1 = (String) stringList1.get(0);

    System.out.println(s1.toUpperCase());

 

    // now with generics in JDK 5

    List<String> stringList2 = new ArrayList<String>();

    stringList2.add("Java 5.0");

    stringList2.add("with generics");

    // no need for type casting

    String s2 = stringList2.get(0);

    System.out.println(s2.toUpperCase());

  }

}

 

 

下面是一个有趣的应用:

import java.util.ArrayList;

import java.util.List;

public class ListOfListsTest {

  public static void main(String[] args) {

    List<String> listOfStrings = new ArrayList<String>();

    listOfStrings.add("Hello again");

    List<List<String>> listOfLists = new ArrayList<List<String>>();

    listOfLists.add(listOfStrings);

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

    System.out.println(s); // prints "Hello again"

  }

}

 

四、泛型进阶

对于没有使用泛型处理的代码,在JDK5中,系统会出现编译警告,提示代码为”raw type”

这是兼容的,如果不想看到这个信息,可以做如下处理:

1 使用 –source 1.4 参数编译。

2 使用@SupressWarnings(“unchecked”) annotaion

3 升级为使用泛型

 

如果你声明一个泛型List<atype>,那么List的实现中,atype可以是如下类型:

1 atype的实例

2 atype子类的实例(如果atype是一个class

3 atype的实现类的实例(如果atype是一个接口)

 

泛型和Java对象一样,都有自己的类型,下面两个就是完全独立,没有关系的:

List<Object> list1 = new ArrayList<Object>();

List<String> list2 = new ArrayList<String>();

 

虽然StringObject的子类,但是List<String>可不是List<Object>的子类。

 

再看下面的代码,

import java.util.ArrayList;

import java.util.List;

 

public class AllowedTypeTest {

  public static void doIt(List<Object> l) {

  }

  public static void main(String[] args) {

    List<String> myList = new ArrayList<String>();

    // this will generate a compile error

    doIt(myList);

  }

}

系统会提示编译错误。

 

为了解决类似的问题,JDK5提出了通配符号(?)List<?>,这个声明意味着List可以接收任何对象。

import java.util.ArrayList;

import java.util.List;

 

public class WildCardTest {

 

  public static void printList(List<?> list) {

    for (Object element : list) {

      System.out.println(element);

    }

  }

  public static void main(String[] args) {

    List<String> list1 = new ArrayList<String>();

    list1.add("Hello");

    list1.add("World");

    printList(list1);

 

    List<Integer> list2 = new ArrayList<Integer>();

    list2.add(100);

    list2.add(200);

    printList(list2);

  }

}

 

特别注意,如果你这样声明就不对了:

List<?> myList = new ArrayList<?>();

 

边界通配符 (bounded wildcards)

 

在泛型中,如果你有一个getAverage方法用来返回平均值,你可能要传递integer,float,double等。那么你将参数设置为List<Number>,但是由于List<Number>List<Integer>List<Double>是不同的类型,所以不行。我们还可以用List<?>,但是这样会降低类型安全,因为List<String>也可能发生。

 

JDK5推出upper bounded ,格式如下:

GenericType <? Extends uppderBoundedType>

请看下面的例子:

import java.util.ArrayList;

import java.util.List;

public class BoundedWildcardTest {

  public static double getAverage(List<? extends Number> numberList)

  {

    double total = 0.0;

    for (Number number : numberList)

      total += number.doubleValue();

    return total/numberList.size();

  }

 

  public static void main(String[] args) {

    List<Integer> integerList = new ArrayList<Integer>();

    integerList.add(3);

    integerList.add(30);

    integerList.add(300);

    System.out.println(getAverage(integerList)); // 111.0

    List<Double> doubleList = new ArrayList<Double>();

    doubleList.add(3.0);

    doubleList.add(33.0);

    System.out.println(getAverage(doubleList)); // 18.0

  }

}

 

It’s so ok

如果在main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值