Java泛型类的继承关系
2016-03-03 11:18
429 查看
引言
类型兼容的对象可以进行赋值,如可将一个 Integer 对象传给一个 Object 对象,因为 Object 是 Integer 的基类。[code]Object someObject = new Object(); Integer someInteger = new Integer(10); someObject = someInteger; // OK
对于方法的参数,也可传递类型兼容的对象。如 Integer 是一个 Number ,故如下代码可正确执行。
[code]public void someMethod(Number n) { /* ... */ } someMethod(new Integer(10)); // OK someMethod(new Double(10.1)); // OK
类型兼容不能直接运用到泛型类型上,考虑如下方法:
[code]public static void boxTest(Box<Number> box) { System.out.println(box.get()); }
该方法接受类型为
Box<Number>的参数,那么该方法是否接收类型为
Box<Integer>或
Box<Double>的参数?要回答这个问题,首先要清楚以下两个问题:
1.
boxTest的字节码签名是什么?
2.
Box<Number>的子类型应满足什么条件?
1. BoxTest的字节码签名
这个话题涉水较深,如果使用 javap -s -c, 只能看到 descriptor 的信息:[code]public static void boxTest(generic.inheritance.Box<java.lang.Number>); descriptor: (Lgeneric/inheritance/Box;)V Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_0 4: invokevirtual #3 // Method generic/inheritance/Box.get:()Ljava/lang/Object; 7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 10: return
由上面的信息只能推导出 boxTest 只接受类型为 Box 的参数。而 Box 是泛型类,其基类为 Object. 需要使用 javap -v 才能确定 boxTest 完整签名信息:
[code]public static void boxTest(generic.inheritance.Box<java.lang.Number>); descriptor: (Lgeneric/inheritance/Box;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_0 4: invokevirtual #3 // Method generic/inheritance/Box.get:()Ljava/lang/Object; 7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 10: return LineNumberTable: line 11: 0 line 12: 10 Signature: #19 // (Lgeneric/inheritance/Box<Ljava/lang/Number;>;)V
Signature: #19才是
boxText的完整签名信息,表示该方法之接受类型为泛型类型
Box<Number>的参数。接下来确定
Box<Number>的子类型。
2. 泛型类的子类型
泛型类或接口的子类型创建方式与创建常规的类或接口的子类型创建方式一致,即使用 extends 或 implements 关键字。以 Collections 为例,
ArrayList<E>实现了
List<E>, 同时
List<E>扩展自
Collections<E>. 故
ArrayList<E>是
List<E>的子类型,
List<E>是
Collections<E>的子类型。只要类型参数 E 一致,这三个类的继承关系就得到保持。
由于
Box<Number>和
Box<Integer>的类型参数不同,故两者没有继承关系,其关系可如下表示:
因此,
testBox(Box<Number>)不接收类型为
Box<Integer>和
Box<Double>的参数。
小结
对于类 A 和类 B,MyClass<A>和
MyClass<B>没有任何继承关系,即使 A 是 B 的子类。
MyClass<A>和
MyClass<B>的共同子类为 Object.
拓展:包含额外类型参数的继承关系
对于自定义的列表接口, PlayloadList 包含了一个额外的类型参数 P, 表示列表中的每个元素都关联了类型为 P 的元素。设存在方法:[code]interface PayloadList<E,P> extends List<E> { void setPayload(int index, P val); ... }
以下的三个 PayloadList 都是
List<String>的子类:
PayloadList
<String,String>
PayloadList
<String,Integer>
PayloadList
<String,Exception>
继承关系如下所示:
相关文章推荐
- Hadoop集群(第7期)_Eclipse开发环境设置
- java arrays类学习
- 【leetcode】【86】Partition List
- 《深入JAVA虚拟机》读书笔记
- myeclipse10.7破解后导出war包错误
- Java并发编程:Lock
- java使用poi读取ppt文件和poi读取excel、word示例
- Hadoop集群(第5期副刊)_JDK和SSH无密码配置
- Java log4j详细教程
- java.lang.String.isEmpty()的用法
- eclipse出现Failed to load the JNI shared library
- JAVA8 十大新特性详解
- spring线程池ThreadPoolExecutor配置并且得到任务执行的结果
- 如何利用Ffmpeg进行视频截图
- 解决方法数超65536(java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536)
- Java中的Copy-On-Write容器(二) --CopyOnWriteArraySet
- 【leetcode】【82】Remove Duplicates from Sorted List II
- JAVA中有关逆变和协变类型的详解
- Java多态
- RXJava