温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

JDK5.0新特性的泛型怎么理解

发布时间:2022-01-11 10:09:57 来源:亿速云 阅读:157 作者:柒染 栏目:编程语言

本篇文章给大家分享的是有关JDK5.0新特性的泛型怎么理解,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

没有参数的情况下使用泛型
   既然在J2SE 5.0中收集类型已经泛型化,那么,原来的使用这些类型的代码将如何呢?很幸运,他们在JAVA 5中将继续工作,因为你能使用没有参数的泛型。比如,你能继续像原来一样使用List接口,正如下面的例子一样。

List stringList1 = new ArrayList();
stringList1.add("Java 1.0 - 5.0");
stringList1.add("without generics");
String s1 = (String) stringList1.get(0);

一个没有任何参数的泛型被称为原型(raw type)。它意味着这些为JDK1.4或更早的版本而写的代码将继续在java 5中工作。

尽管如此,一个需要注意的事情是,JDK5编译器希望你使用带参数的泛型。否则,编译器将提示警告,因为他认为你可能忘了定义类型变量s。比如,编译上面的代码的时候你会看到下面这些警告,因为第一个List被认为是原型。

Note: com/brainysoftware/jdk5/app16/GenericListTest.java
       uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

当你使用原型时,如果你不想看到这些警告,你有几个选择来达到目的:
1.编译时带上参数-source 1.4
2.使用@SupressWarnings("unchecked")注释
3.更新你的代码,使用List. List的实例能接受任何类型的对象,就像是一个原型List。然而,编译器不会报错。

使用 ? 通配符
  前面提过,如果你声明了一个List, 那么这个List对aType起作用,所以你能储存下面这些类型的对象:
1.一个aType的实例
2.它的子类的实例(如果aType是个类)
3.实现aType接口的类实例(如果aType是个接口)
但是,请注意,一个泛型本身是个JAVA类型,就像java.lang.String或java.io.File一样。传递不同的类型变量给泛型可以创建不同的JAVA类型。比如,下面例子中list1和list2引用了不同的类型对象。

List

list1 = new ArrayList();
List

list2 = new ArrayList();
 
list1指向了一个类型变量s为java.lang.Objects 的List而list2指向了一个类型变量s为String 的List。所以传递一个List给一个参数为List的函数将导致compile time错误。下面列表可以说明:

public class AllowedTypeTest {
 public static void doIt(Listl) {
 }
 public static void main(String[] args) {
   ListmyList = new ArrayList();
   // 这里将产生一个错误
   doIt(myList);
 }
}
上面的代码无法编译,因为你试图传递一个错误的类型给函数doIt。doIt的参数是List二你传递的参数是List
可以使用 ? 通配符解决这个难题。List 意味着一个对任何对象起作用的List。所以,doIt可以改为:

public static void doIt(List l) {}

在某些情况下你会考虑使用 ? 通配符。比如,你有一个printList函数,这个函数打印一个List的所有成员,你想让这个函数对任何类型的List起作用时。否则,你只能累死累活的写很多printList的重载函数。下面的列表引用了使用 ? 通配符的printList函数。

public class WildCardTest {

 public static void printList(List list) {
   for (Object element : list) {
     System.out.println(element);
   }
 }
 public static void main(String[] args) {
   Listlist1 = new ArrayList();
   list1.add("Hello");
   list1.add("World");
   printList(list1);

   Listlist2 = new ArrayList();
   list2.add(100);
   list2.add(200);
   printList(list2);
 }
}

这些代码说明了在printList函数中,List表示各种类型的List对象。然而,请注意,在声明的时候使用 ? 通配符是不合法的,像这样:

List myList = new ArrayList(); // 不合法

如果你想创建一个接收任何类型对象的List,你可以使用Object作为类型变量,就像这样:

List
myList = new ArrayList();
 
在函数中使用界限通配符
在之前的章节中,你学会了通过传递不同的类型变量s来创建不同JAVA类型的泛型,但并不考虑类型变量s之间的继承关系。在很多情况下,你想一个函数有不同的List参数。比如,你有一个函数getAverage,他返回了一个List中成员的平均值。然而,如果你把List作为getAverage的参数,你就没法传递List或List参数,因为List和List和List不是同样的类型。

你能使用原型或使用通配符,但这样无法在编译时进行安全类型检查,因为你能传递任何类型的List,比如List的实例。你可以使用List作为参数,但是你就只能传递List给函数。但这样就使你的函数功能减少,因为你可能更多的时候要操作List或List,而不是List

J2SE5.0增加了一个规则来解决了这种约束,这个规则就是允许你定义一个上界(upper bound) 类型变量.在这种方式中,你能传递一个类型或它的子类。在上面getAverage函数的例子中,你能传递一个List或它的子类的实例,比如Listor List

使用上界规则的语法这么定义的:GenericType<!--xtends upperBoundTy--&gt. 比如,对getAverage函数的参数,你可以这么写List<!--xtends Numb--&gt. 下面例子说明了如何使用这种规则。
public class BoundedWildcardTest {
  public static double getAverage(List<!--xtends Numb--&gt numberList)
  {
    double total = 0.0;
    for (Number number : numberList)
      total += number.doubleValue();
    return total/numberList.size();
  }
 
  public static void main(String[] args) {
    List
由于有了上界规则,上面例子中的getAverage函数允许你传递一个List或一个类型变量是任何java.lang.Number子类的List。

下界规则
关键字extends定义了一个类型变量的上界。通过使用super关键字,我们可以定义一个类型变量的下界,尽管使用的情况不多。比如,如果一个函数的参数是List<!--uper Integ--&gt,那么意味着你可以传递一个List的实例或者任何java.lang.Integer的超类(superclass)。

创建泛型

前面的章节主要说明了如何使使用泛型,特别是集合框架中的类。现在我们开始学习如何写自己的泛型。

基本上,除了声明一些你想要使用的类型变量s外,一个泛型和别的类没有什么区别。这些类型变量s位于类型后面的<>中。比如,下面的Point就是个泛型。一个Point对象代表了一个系统中的点,它有横坐标和纵坐标。通过使Point泛型化,你能定义一个点实例的精确程度。比如,如果一个Point对象需要非常精确,你就把Double作为类型变量。否则,Integer 就够了。
package com.brainysoftware.jdk5.app16;
public class Point
在这个例子中,T是Point的类型变量 。T是getX和getY的返回值类型,也是setX和setY的参数类型。此外,构造函数结合两个T参数。
使用point类就像使用别的类一样。比如,下面的例子创建了两个Point对象:ponint1和point2。前者把Integer作为类型变量,而后者把Double作为类型变量。

Point
泛型使代码在编译时有了更严格的类型检查。特别是在集合框架中,泛型有两个作用。第一,他们增加了对集合类型在编译时的类型检查,所以集合类所能持有的类型对传递给它的参数类型起了限制作用。比如你创建了一个持有strings的java.util.List实例,那么他就将不能接受Integers或别的类型。其次,当你从一个集合中取得一个元素时,泛型消除了类型转换的必要。
泛型能够在没有类型变量的情况下使用,比如,作为原型。这些措施让Java 5之前的代码能够运行在JRE 5中。但是,对新的应用程序,你最好不要使用原型,因为以后Java可能不支持他们。
你已经知道通过传递不同类型的类型变量给泛型可以产生不同的JAVA类型。就是说List和List的类型是不同的。尽管String是java.lang.Object。但是传递一个List给一个参数是List的函数会参数会产生编译错误(compile error)。函数能用 ? 通配符使其接受任何类型的参数。List 意味着任何类型的对象。最后,你已经看到了写一个泛型和别的一般JAVA类没有什么区别。你只需要在类型名称后面的<>中声明一系列的类型变量s就行了。这些类型变量s就是返回值类型或者参数类型。根据惯例,一个类型变量用一个大写字母表示。

以上就是JDK5.0新特性的泛型怎么理解,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI