`
feng_gladys
  • 浏览: 7784 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Java Generic

阅读更多

什么是泛型:

       Generic programming means to write code that can be reused for objects of many different types. 摘自《 Core java  

 

为什么使用泛型

       主要是为了类型转换。如果不使用泛型,那么每次都得显式的就行类型转换。

如:

       不使用泛型:

       List list = …

    String str = (String)list.get(1);  

    使用泛型:

    List<String> list = …

    String str =  list.get(1);  

 

如何定义泛型:

       使用 <Type variable> 中带有类型,该类型可以是具体类型 . 比如 : String.

也可以不是具体类型,比如 <? Extends Number>. 具体类型 (reifiable type) 和非具体类型 (unreifiable type)

       (非)具体化类型后面再介绍

       < Type variable > 即表明声明了泛型,可以在类、方法、字段等处定义泛型。

 

什么是类型参数( type parameter   参数化类型( parameterized type

       比如,类 List<String> ,称 String 为类型参数。 List<String> 为参数化类型,因为 List String 参数化了。  

 

 

子类型( subtypes )及替换原则  

    Integer Number 的子类,能放置 Number 的地方都能放置 Integer ,这便是 Java 中的替换原则。

    Substitution Principle: a variable of a given type may be assigned a value of any subtype of that type, and a method with a parameter of a given type may be invoked with an argument of any subtype of that type -- 摘自 Java Generics & Collections  

    数组 Integer[] Number[] 的子类,那是不是 List<Integer> 也是 List<Number> 的子类?其实不是,他们其实是同一类型。可以通过以下代码判断。

List<Number> numList = …

List<Integer> intList = …

System.out.println(numList.getClass() == intList.getClass())  

       如果我们需要在泛型中拥有类似于数组的该特性( Integer[] Number[] 的子类),我们就得使用通配符 (wildcard).  
 

通配符 (wildcard) 访问原则

       上述说过,数组 Integer[] Number[] 的子类, List<Integer> 确不是 List<Number> 的子类。要实现类似于数组的该特性,就需要通配符来实现 : List< ? extends Number> .

       表示通配符,表示任意类型(继承 Object 的任意类型)。

       ? extends T 表示继承或实现 T 的类型。即 T 的任意子类型 , 比如 ? extends Number 表示继承自 Number 的任意类型,可以是 Integer, Double …

       ? super T 表示 T 的任意父类型( super type ),比如: ? Super ArrayList 表示 ArrayList 的任意父类型,可以是 List, AbstractList…

       表示 ? extends Object  
 

       通过通配符,我们可以实现类似于数组的功能:

       List<Integer>  intList = …;

       List<Number> numList=…;

       List<? Extends Number> list1 = intList;

       List<? Extends Number> list2 = numList;

       List<? Super Number> list3 = numList;  

       这样我们可以向数组一样进行类型转换。但却不能像数组一样进行以下方式的赋值:

       Number[] nums = …

       Nums[0] = Integer.valueOf(2)..  

       如果编写以下代码:

       List<? Extends Number> list =  … ;

       List.add(Integer.valueOf(2)) // 编译器报错。

       List.add(Double.valueOf(2)) // 编译器报错  

    为什么呢? <? Extends Number> 不是表示 Number 的任意子类型么? 使用替换原则不是应该正确的么?

       该问题的源头就是因为 <? Extends Number> 表示 Number 的子类型。但是我们却不知道到底是哪个具体的类型。因此 List< ? extends Number> 可以指向其任意的子类型。比如, List<Integer>, List<Number>,List<Double>. 如果是 list 是指向 ArrayList<Double>, list.add(Integer.valueOf(2)) 合法的话,那么 list 中就存在 Double Integer Number 子类型的对象, ArrayList<Double> 中的元素类型就不一样。那么 list.get(..) 就有可能返回 Integer 类,就可能出现问题,由于泛型有个基本原则:

    Cast-iron guarantee:

    the implicit casts added by the compilation of generics never fail.

  •  
    •  
      •  
        •  

                -- 摘自 Java Generics & Collections  

所以编译器在编译级别就将可能导致类型转化的错误屏蔽掉。

    当然我们可以调用 list.add(null), 因为 null 是任意类型的子类型,可以安全的使用,但很多时候没有用处。 

       如果使用 list.get(..) 就不会有问题,因为 list 存的就是 Number 子类对象,任何子类都能转为其基类( Number )。  

       同样的道理,以下代码无法编译:

       List<? Super Integer> list = …

       Integer in =  list.get(0); // 编译过不去

       因为 List 存的是 Integer 的基类型,但是我们并不知道具体是哪个基类。所以就无法进行转化 , 当然我们可以调用 Object obj = list.get(0)

       如果使用 list.add(Integer.valueOf(2)) 却不会有问题,因为 list 存的是 Integer 的父类,那么必然可以存 Integer 类型。  

       因此利用 < ? extend …> <? Super …> 时,一般使用一个原则:

The Get and Put Principle: use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard when you both get and put.

  •  
    •  
      •  
        •  

                -- 摘自 Java Generics & Collections

类型参数 VS 通配符

       比如我们需要将一个list的数据拷贝到另一个list中。

假设方法在类Collections中定义:

public static <T> void copy(List<? super T> dst, List<? extends T> src)  

List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");

List<Integer> ints = Arrays.asList(5, 6);  

List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");

List<Integer> ints = Arrays.asList(5, 6);

Collections.copy(objs, ints);

assert objs.toString().equals("[5, 6, four]");  

由以下方法调用, <Object> 表示 T Object

Collections.copy(objs, ints);

Collections.<Object>copy(objs, ints);

Collections.<Number>copy(objs, ints);

Collections.<Integer>copy(objs, ints);  

比较以下几种方法签名:

1:public static <T> void copy(List<T> dst, List<T> src)

2:public static <T> void copy(List<T> dst, List<? extends T> src)

3:public static <T> void copy(List<? super T> dst, List<T> src)

4:public static <T> void copy(List<? super T> dst, List<? extends T> src)  

比较:

1 :限制最大,必须要求 dst src 是同一类型,比如同是 List<Integer>.

       该方法不能用于 上述的例子 collectioins.copy(objs,ints)  

2: 仅仅使用于T为Object时。即Collections.<Object>copy(objs, ints)方式  

3:仅仅使用于T为Integer时,Collections.<Integer>copy(objs, ints);  

4 :可应用于 T Object Number Integer 时。  

以上例子摘自 – Java Generic & Collections  

简单的总结一下:

       泛型方法签名尽可能的使用 wildcard ,其可用范围更广。如果需要严格限制为同一类型时,就可以使用 type parameter  

 

 

Wildcard capture

       译为 捕捉通配符??? 何为 wildcard capture. 顾名思义 : 就是捕捉通配符的类型。 看以下例子:

       Pair<T>有first 和second两个变量。分别有对应的set, get 方法。  

       public static void swap(Pair<?> p){

             ? t = p.getFirst(); // ERROR

             p.setFirst(p.getSecond());

             p.setSecond(t);  

       }

       但是用T确实没有问题:

public static <T> void swapHelper(Pair<T> p)

{

   T t = p.getFirst();

   p.setFirst(p.getSecond());

   p.setSecond(t);

}  

因此我们经常使用swapHelper(Pair<T> p)来实现swapHelper(Pair<?> p):

public static void swap(Pair<?> p) { swapHelper(p); }  

这种情况,我们叫T 捕捉了 通配符(T captures the wildcard).我们并不知道wildcard表示什么类型,但是我们知道其必然是一个明确的类型。因此可以用T去捕捉它。(这里有点绕,知道T可以捕捉?即可)。  

       注意的是:要用T捕捉?,那么要保证wildcard必须是表示同一、明确的类型(尽管我们不知道这是什么类型)。

       比如 ArrayList<List<T>>就不能用来捕捉ArrayList<List<?>>,因为ArrayList可能包含两个或以上List<?>,每个List<?>拥有不同的类型。  

以上例子摘自—Core Java  
 

擦除( erasure  

泛型定义:  

泛型方法:  

Bridge Method  

具体化类型 (reifiable type)  

泛型对象创建  

消除 Unchecked warning  

反射与泛型  

Effective generic

评论

相关推荐

    Java Generic 介绍 (pdf)

    标题中的“Java Generic 介绍”涵盖了泛型的基本概念、使用方式以及其背后的原理。以下是对这一主题的详细阐述: 1. **泛型的基本概念**:泛型是Java中的一种模板类或接口,它允许开发者在定义类、接口和方法时使用...

    Java - Generic

    在Java编程语言中,泛型(Generic)是一个强大的特性,它允许我们在编译时检查类型安全,并且可以消除运行时的类型转换。泛型引入的主要目的是提高代码的重用性、安全性和效率,同时减少类型转换的繁琐工作。这篇...

    android 浅复制和深复制-Java Generic Deep Copy 篇

    本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...

    java-generic.rar_泛型

    在《java-generic.rar》压缩包中包含的《java generic.pdf》文件,很可能是详细阐述了以下几个关于Java泛型的核心知识点: 1. **类型参数化**:泛型的核心在于类型参数化,这使得我们可以在定义类、接口和方法时...

    Japag - Java generic command line GUI-开源

    【Japag - Java generic command line GUI 开源项目详解】 Japag,全称为 Java Application for Providing a Generic GUI,是一个开源项目,专为那些希望通过图形用户界面(GUI)而非命令行来运行各种命令行应用...

    java高手真经 光盘源码

    java高手真经 全光盘源代码 打包rar 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例Hello...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    Java高手真经(编程基础卷)光盘全部源码 免积分

    看到那些要积分的很不酸,发布免费版本。 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    Java高手真经(编程基础卷)光盘全部源码

    看到很多人都分卷打包的,下载很是不方便,还浪费积分,我就整合压缩打包到一个包里面,里面包含全部...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    java 泛型接口示例

    Java 泛型是Java SE 5.0引入的一项重要特性,极大地增强了代码的类型安全性和重用性。泛型接口是泛型在接口中的应用,它允许我们在接口中定义带有类型参数的方法,使得实现该接口的类可以使用不同的数据类型。下面...

    Generic_MT4_java_generic_mt4_

    标题中的"Generic_MT4_java_generic_mt4_"暗示了一个与MetaTrader 4 (MT4)交易平台相关的编程项目,可能是一个自定义的智能交易系统(Expert Advisor,EA)或指标,使用了Java语言,并且具有通用性。这个“Generic_...

    Java中的泛型方法演示代码

    Java中的泛型是Java SE 5.0引入的一项重要特性,极大地增强了代码的类型安全性和重用性。泛型方法是泛型概念的一个关键部分,它允许我们在方法签名中使用类型参数,从而使方法能够处理不同类型的参数。在这个“Java...

    Java1.5泛型指南中文版(Java1.5 Generic Tutorial)

    Java1.5泛型指南中文版(Java1.5 GenericTutorial)

    java collection framework

    此外,还介绍了一种名为 JGL (Java Generic Library) 的第三方库,该库在 Java Collection Framework 出现之前就已经存在,并且提供了一些额外的功能。 #### 八、总结 《Java Collection Framework》这本书不仅是...

    java 泛型的使用 详细讲解

    ### Java泛型的使用详细讲解 #### 一、引言 在Java开发中,泛型是一种重要的语言特性,它能够帮助开发者在不增加代码量的情况下处理多种数据类型,同时还能保持代码的清晰度和可读性。本文将详细介绍Java泛型的...

Global site tag (gtag.js) - Google Analytics