分享

古月白狐 残空望月 万杯不醉 千月星痕 Java泛型(续)

 starsiday 2006-08-16

Java泛型(续)

首先对上次的泛型做一些补充说明

1<? extends Class>是一种限制通配符类型,它可以接受所有<Class>以及Class的子类型。然而调用代价是,只读访问。

 

2TClass<T>

{
 T obj;

}

 

这个T是不能拿来实例化对象的,只能用来进行转型,和限定参数类型和返回类型。

 

3.关于静态方法的泛型

public static <T> T gMethod (List<T> list) { ... }

 

e.g.

public class Circle {

 

    public static <T> T gMethod(List<T> list) {

       System.out.println("come here");

       return list.get(0);

    }

 

    public static void main(String args[]) {

       List<Person> pl = new LinkedList<Person>();

        pl.add(new Person("sharkmao",622));

       Person p = Circle.gMethod(pl);

    }

}

 

 

4.一个BT的语法

<T extends Object & Comparable<? super T>>

T  max (Collection<? extends T> coll) {}

C++中的泛型已经相当恶心了,没有想到java中的泛型也没有好到哪里去。

T必须实现Comparable接口,而且Comparable接口比较的类型必须是T的超类

e.g.

public abstract class Shape implements Comparable<Shape>{}

 

LinkedList<Shape> sList = new LinkedList<Shape>();

Shape s = Collections.max(sList);

 

之所以比较的是Shape的超类,是因为這是合理的,因为不知道比较出来的结果会是RectCircleStroke但无论如何它们都可以向上转型为Shape

 

下面说说java泛型中擦拭这个概念。

 

江南白衣blog的回复中有这么一个例子

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

 

import junit.framework.TestCase;

 

class TClass<T> {

}

 

class GoodClass<T> extends TClass<String> {

    public ParameterizedType getClassT() {

       return (ParameterizedType) getClass().getGenericSuperclass();

    }

}

 

class BadClass<T> extends TClass<T> {

    public ParameterizedType getClassT() {

       return (ParameterizedType) getClass().getGenericSuperclass();

    }

}

 

public class GenericsTest extends TestCase {

 

    private void print(Type[] targs) {

       System.out.print("actual type arguments are:");

       for (int j = 0; j < targs.length; j++) {

           System.out.print(" instance of " + targs[j].getClass().getName()

                  + ":");

           System.out.println(" (" + targs[j] + ")");

       }

    }

 

    public void testGoodClass() throws Exception {

       ParameterizedType type = new GoodClass<String>().getClassT();

       Type[] types = type.getActualTypeArguments();

       print(types);

 

       assertEquals(TClass.class, type.getRawType());

       assertEquals(String.class, types[0]);

    }

 

    /*public void testBadClass() throws Exception {

       ParameterizedType type = new BadClass<String>().getClassT();

       Type[] types = type.getActualTypeArguments();

       print(types);

 

       assertEquals(TClass.class, type.getRawType());

       assertEquals(String.class, types[0]);

    }*/

}

 

 

注意GoodClassBadClass唯一的不同就是在继承的时候一个指定了父亲的类型是String,而另一个没有指定父亲的类型。

但是测试testBadClass方法会失败。

下面是一段对擦拭这个概念阐述的一段话

实际上BadClass<String>()实例化以后Class里面就不包括T的信息了,对于Class而言T已经被擦拭为Object。而真正的T参数被转到使用T的方法(或者变量声明或者其它使用T的地方)里面(如果没有那就没有存根,这里指ParameterizedTyp),所以无法反射到T的具体类别,也就无法得到T.class
getGenericSuperclass()Generic继承的特例,对于这种情况子类会保存父类的Generic参数类型,返回一个ParameterizedType,这时可以获取到父类的T.class了,这也正是子类确定应该继承什么T的方法。
我们应该利用这种特性,这对实现模版方法非常有用。

就我目前的理解,一个使用了泛型的类是无法得到自己的T.class的,只有它的子类在继承的时候,为父类指定T的类型(当然父类中有Class<T>clazz这个属性),然后子类中就才可以获得并且使用这个类型。

 

后来看了一些对java泛型的评论

Java的范型实现来自于一个叫做Pizza的项目。后来呢改名叫做GJ,再后来通过JSR被融合进Java语言。由于Java的范型实现中有一个重要的设计目标,即使范型实现能够运行于现有的、未经修改的JVM上。不修改JVM当然看上去很美,但也会带来一大堆稀奇古怪的限制。
Java
的范型中,得不到一般范型实现所能获得的执行效率上的提高。原因在于Java中的范型类在编译时,编译器会将类型参数替换回object。为了讨 JVM的欢心,编译器自动加入了你并没有写过的类型转换操作。因此你得到的仅仅是语法上的甜头,而没有获得执行效率的提高。这是一个问题。

第二个问题,也是更严重的问题是,Java的范型实现在运行时偷换了编译时的实际类型,当你对一个范型的List使用反射功能时,你可不知道这个List是个什么类型的List。由于失去了类型信息,动态代码生成功能和反射功能都没法使用。只能在接口中多一个Class参数用来指明类型了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多