`
冰云
  • 浏览: 143235 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

Generics Types 泛型学习笔记<二>

阅读更多

Generics Types 泛型学习笔记<>

作者:冰云
时间:2004-02-24
联系:icecloud(AT)sina.com
Bloghttp://icecloud.51.net

首先我要特别感谢Schlemiel,他指出了类型协变的问题。其实我以前也看到过gigix翻译的那篇文,但是没看懂也没经大脑。经Schlemiel一提醒,我才意识到,这是泛型的规范。再翻出来看,如醍醐灌顶,真良师益友也。

我写文章的目的,就是为了能够找到更多同好进行交流。没有交流,没有氛围,绝对不会有提高。谢谢Schlemiel,每次读他的文章或评论,都能受到很大的启发。

如果需要深入了解泛型,请阅读程序员杂志20037期,或

http://gigix.cool2u.net/download/Variance_in_Java.pdf

 

ok,继续上次的学习笔记。这篇22页的文章正好读了3天。每天从地铁东四十条到西直门,每次读7页。如果哪位晚上6:30-7:00间看到地铁上有个人拿着本电脑书在读,不妨上来问问是不是俺 ^___^||

另:后面文中每章出现了不少重点,我就按照和文中章节一样的标题。Notes则自己编号。

这次特地把字体变为14px,不知道各位看起来如何啊?会不会太大?

5 泛型方法(函数)

 

根据上一条,既然通配符类型是只读的,那么怎样才能在函数中写入呢?这就引入了泛型函数(Generic Mehtods):

 

 

    <T> static void fromArrayToCollection(T[] a, Collection<T> c) {

       for (T o : a){

           c.add(o); //correct

       }

    }  

    Collection<Object> co = new ArrayList<Object>;

    Collection<String> cs = new ArrayList<String>;

    fromArrayToCollection(new Integer[100], co); //correct

    fromArrayToCollection(new Number[100], cs); // error

 

 

    可以知道,不需要传递世纪参数到泛型方法,编译器会自行推断类型。

那么,什么时候使用泛型方法,什么时候使用通配符类型呢?可以这样理解:

 

Note 5: 可以采用泛型方法来保证读写操作的类型安全。泛型方法相当于原来的多态方法,它的效果是允许执行时选用不同的参数类型,而通配符方法相当于接受Object的方法。

文:This tells us that the type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites.

考虑下面的方法,

      

       public static <T, S extends T> void copy (

              List <T> dest, List <S> src) ();

       public static <T> void copy (

              List <T> dest, List <? extends T> src) ();

 

 

    哪一个更清楚明了一点?因为S只用了一次,因此可以用通配符类型取代S。这样更简练。通配符类型的另一个好处是,他们可以用在方法外面,作为值域(fields)、本地变量(local variables)或数组的类型。如

 

      

       static List<List<? extends Shape>> history

              = new ArrayList<List<? extends Shape>>();

 

       public void drawAll(List<? extends Shape> shapes){

           history.addLast(shapes);

       }

 

 

说实话,我看到上面的变量定义简直想骂人。这个是定义了一个ListList,也就是history是保存List<? extends Shape>List

 

6 泛型与旧代码

在泛型代码中使用旧代码可能导致类型安全隐患。

 

      

    public interface Inventory {

       void setCats(Collection c);

       Collection getCats();

    }

    Collection<Cat> c = new ArrayList<Cat>();

    c.add(new BlackCat());

    Inventory.setCats(c);

    Collection<Cat> k = Inventory.getCats();

 

 

Note 6: 一般编译器无法知道Collection引用了何种类型,这样的没有带有类型的Collection称为row type。这样的类型表示一些未知类型,相当于Collection<?>

原文:The compiler has no way of knowing what kind of collection the type Collection refers to. It’s called a raw type. It’s more accurate to say that the type Collection denotes a collection of some unknown type like Collection<?>.

 

这种情况下,把Collection<?>赋值给Collection<Cat>是合法的,但是会出现一个unchecked warning,未检查警告。表示编译器无法保证它的正确性。因此使用旧代码时候请注意unchecked warning.

 

Note 7: 泛型编译时会被编译器进行一次称为erasure的过程。可以认为就是将泛型的代码转换为非泛型版本。最终的结果是:JVM不会检查类型安全和完整性,就算出现了unchecked warning也一样。Erasure会删除所有的泛型信息,如将List<String>转换为List,所有的类型变量被替换为最上限的,如Object。并且不管结果代码如何,都会增加类型转换。

原文:Generics are implemented by the Java compilers as a front-end conversion called ensure. It just like a source-to-source translation. As a result, the type safety and integrity of the JVM are never at risk, even in presence of unchecked warnings. Erasure throws out  all type information between angle brackets. For example, List<String> is converted into List. All remaining uses of type variables are replaced by the upper bound type variable (usually Object). And, whenever the resulting code isn’t type-correct, a cast to the appropriate type is inserted.

 

       在旧代码中使用泛型代码。与上面情况类似,会出现unchecked warning.

 

7 Fine Print 美好蓝图?(搞不懂作者的意图)

   

       泛型类被所有的它的子类共享。

 

             

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

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

    assert(l1.getClass()==l2.getClass()); // return true

 

 

Note 8: 所有的泛型类拥有相同的runtime类(其实从上面一条可以知道),并且,静态变量和方法也会在类的实例间共享。这就是为何在静态方法、变量或初始化中引用类型参数是非法的。

原文:All instances of generics class have the same run-time class. As consequence, the static variables and methods of a class are also shared among all the instances. That’s why it is illegal to refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or initializer of a static variable.

 

    另一个隐含的事实,是无法判断一个类是否instanceof 其泛型类。或类型转换一个对象到一个泛型类型。

 

             

    Collection<String> cs = new ArrayList<String>;

    if (cs instanceof Collection<String>) {} //非法

    (Collection<String>) cs; // unchecked warning

   

    <T>T badCast(T t, Object o) {return (T)o};// unchecked warning

 

 

Note 9: 类型变量在运行时不存在!这意味着泛型不会占用时间或空间的性能,但不幸的是,你不能可靠的使用类型转换。

原文:type variables don’t exist at run time. This means that they entail no performance overhead in either time nor space. It also means that you can’t reliably use them in casts.

 

数组可能无法成为一个参数类型。除非是一个通配符类型。

 

             

    List<String> [] lsa = new List<String>[10]; // 不允许

                     = new List<?>[10]; // 允许

    Object o = isa;

    Object[] oa = (Object[])o;

    oa[1] = new ArrayList<Integer>();

    String s = lsa[1].get(); //允许的情况下,runtime error

 

 

可以声明类型变量的数组,但是不能初始化(new)建立一个新数组。如new T[100],因为类型变量运行时并不存在。

 

 

词汇表:

参数类型:parameterized type,形如:new ArrayList<?>new ArrayList<String>

类型变量:type variable,形如:<T> T getCollection()…

通配符类型:wildcard type,形如:new ArrayList<?>

有界通配符类型:bounded wildcard type,形如:new ArrayList<? extends Object>

原生类型:raw type,指在泛型代码中使用Collection, ArrayList等旧形式

未检查警告:unchecked warningJava1.5代码安全警告。

 

To be continue ...

      

 

版权声明:

本文由冰云完成,首发于CSDN,作者保留中文版权。

未经许可,不得使用于任何商业用途。

欢迎转载,但请保持文章及版权声明完整。

如需联络请发邮件:icecloud(AT)sina.com

 



分享到:
评论

相关推荐

    6-generics(泛型6).pdf

    let output = identity&lt;string&gt;("myString"); // type of output will be 'string' ``` 2. 利用类型推论,由编译器根据传入的值自动推断类型: ```typescript let output = identity("myString"); // type of ...

    .Net 2.0 泛型高级编程(Professional .NET 2.0 Generics )

    8. 泛型与继承:泛型类可以被其他泛型类或非泛型类继承,这使得我们可以构建复杂的类层次结构,例如 `class Derived&lt;T&gt; : Base&lt;T&gt;`。 9. 泛型与多态:泛型不仅提供了静态类型的安全性,还支持多态性。通过泛型,...

    generics-tutorial.pdf

    自JDK 1.5以来,Java编程语言引入了一系列重要的扩展功能,其中最重要的一个特性就是泛型(Generics)。本文档旨在向读者介绍Java中的泛型,并通过与类似语言如C++中的模板进行对比,帮助读者理解其相似性和差异性。...

    java 泛型类的类型识别示例

    在Java编程语言中,泛型(Generics)是一种强大的特性,它允许我们在编写代码时指定容器(如集合)可以存储的数据类型。这提高了代码的安全性和效率,因为编译器可以在编译时检查类型,避免了运行时...

    Pro C# 2008 and the .NET 3.5 Platform, Fourth Edition

    &lt;br&gt;&lt;br&gt;Explore five new chapters of content—including the grammar of the common intermediate language (CIL), .NET generics, and object serialization services. &lt;br&gt;Discover all the new .NET 3.5 ...

    .NET基础之自定义泛型分析

    在.NET中泛型使用非常频繁,在控制台应用程序中,默认的引入了System.Collection.Generics名称空间,其中就提供了我们经常使用的泛型:List&lt;T&gt;和Dictionary&lt;T&gt;,相信用过它们的都知道它们的强大。还有一种我们经常...

    Generics with Delphi 2009 Win32

    #### 二、日常应用:TList&lt;T&gt; 示例 ##### A、简单的开始代码 在 Delphi 2009 中,TList 类被泛型化,现在可以表示任何类型的列表。这极大地提高了其灵活性。例如: ```delphi type TMyList = TList&lt;integer&gt;; ...

    Java1.5泛型指南中文版

    Java 1.5引入了泛型(Generics)的概念,这是一个重要的语言特性,它允许开发者在编译时期指定集合或其他数据结构中的元素类型,从而避免了运行时期的类型转换错误。通过使用泛型,开发者可以在编程阶段就确保类型的...

    Addison.Wesley.The.Java.Programming.Language.4th.Edition.Aug.2005.chm

    These tasks must cooperate to behave correctly, and threads meet the needs of cooperative multitasking.&lt;br&gt;&lt;br&gt;Chapter 15Annotationsdescribes the annotation types used to document some of the extra-...

    C# 学习笔记 通俗 实例讲解

    C# 学习笔记:泛型详解与实例 在C#编程中,泛型是一种强大的工具,它允许我们在不牺牲类型安全的情况下创建可重用的数据结构和算法。泛型是自C# 2.0版本引入的一个关键特性,极大地提高了代码的效率和可维护性。...

    泛型和方法

    在实例化泛型类时,可以指定具体的类型,如`MyGenericClass&lt;String&gt; instance = new MyGenericClass&lt;&gt;();`。 泛型方法则是在方法签名中使用类型参数,如`public &lt;T&gt; void genericMethod(T t) {...}`。这里,`&lt;T&gt;`...

    Java 泛型(Generics)使用说明

    环境:Windows XP Professional、JDK 1.6、Ant 1.7&lt;br&gt;说明:Java泛型的动机是为解决类型转换在编译时不报错的问题。另外由于“范型编程”(Generic Programming)的推广,于是2004年JDK 5.0引用范型标准。本例子说明...

    Generics_in_the_Java_Programming_Language译文

    3. 使用泛型:例如 List&lt;Integer&gt; myIntList = new LinkedList&lt;Integer&gt;()。 泛型的优化: 1. 编译期检查:泛型可以在编译期检查类型的正确性,避免了 ClassCastException。 2. 代码重用:泛型可以将类型参数化,...

    java泛型,java知识

    - 在定义泛型类时,类型参数放置在尖括号`&lt;&gt;`内,如`public class MyClass&lt;T&gt;{...}`,`T`就是类型参数,可以在类的方法中使用。 - 泛型接口与泛型类类似,如`public interface MyInterface&lt;E&gt;{...}`。 - 泛型方法...

    Java泛型:概念、用法与优势

    Box&lt;String&gt; strBox = new Box&lt;&gt;("Hello, Generics!"); int intValue = intBox.getData(); // 通过泛型类获取数据,无需类型转换 String strValue = strBox.getData(); System.out.println("Integer value: " ...

    Java Generics FAQ

    Java泛型的基本概念是提供一种类型安全的集合类,通过在类名或接口名后面加上尖括号`&lt;&gt;`来指定类型参数。例如,`List&lt;String&gt;`表示一个字符串列表,这里的`String`就是类型参数。泛型可以用于类、接口和方法,使得...

    Java编程语言中的泛型

    这里,`&lt;T&gt;` 表示这是一个泛型方法,其中 `T` 是类型参数。该方法可以接受任何类型的参数并打印出来。 **3. 泛型的类型参数** 类型参数可以用来定义泛型类或方法的约束。例如,可以限定类型参数必须实现某个接口或...

    面试必须资料java泛型攻略、

    Java泛型(Generics)是一种在编译时确保类型安全的机制,它允许程序员编写类型安全的通用类或方法,而无需进行显式的类型转换。在Java 1.5引入泛型之前,集合类(如`ArrayList`)只能存储`Object`类型的元素。这...

Global site tag (gtag.js) - Google Analytics