Arn*_*ter 9 java generics inheritance inner-classes
编译具有内部类的泛型类时遇到问题.该类扩展了一个泛型类,也就是内部类.
这里实现的接口:
public interface IndexIterator<Element>
extends Iterator<Element>
{
...
}
Run Code Online (Sandbox Code Playgroud)
通用超类:
public abstract class CompoundCollection<Element, Part extends Collection<Element>>
implements Collection<Element>
{
...
protected class CompoundIterator<Iter extends Iterator<Element>>
implements Iterator<Element>
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
具有编译器错误的通用子类:
public class CompoundList<Element>
extends CompoundCollection<Element, List<Element>>
implements List<Element>
{
...
private class CompoundIndexIterator
extends CompoundIterator<IndexIterator<Element>>
implements IndexIterator<Element>
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
错误是:
type parameter diergo.collect.IndexIterator<Element> is not within its bound
extends CompoundIterator<IndexIterator<Element>>
^
Run Code Online (Sandbox Code Playgroud)
怎么了?代码用eclipse编译,但不用java 5编译器编译(我在mac和eclipse 3.5上使用ant和java 5).不,我无法将其转换为静态内部类.
在Java语言规范,§8.1.3,定义了子类内类型如下的语义:
此外,对于C的每个超类S本身是类SO的直接内部类,有一个与i关联的SO实例,称为关于S的直接封闭的i实例.对象的直接封闭实例关于其类的直接超类(如果有的话)是在通过显式构造函数调用语句调用超类构造函数时确定的.
请注意,封闭实例仅描述为特定类,而不是特定类型.由于泛型类型的所有实例共享同一个类,因此以下代码是合法的:
class Base<E> {
E e;
protected class BaseInner<I extends E>{
E e() { return e; }
}
}
class StrangeSub extends Base<Integer> {
protected class StrangeSubInner extends Base<String>.BaseInner<String> {}
}
Run Code Online (Sandbox Code Playgroud)
当然,这可以用来打破类型不变(即导致堆污染):
StrangeSub ss = new StrangeSub();
ss.e = 42;
String s = ss.new StrangeSubInner().e();
Run Code Online (Sandbox Code Playgroud)
eclipse编译器将Java语言规范作为面值,并接受上述代码,甚至不发出"未经检查"的警告.虽然技术上符合JLS,但这显然违反了其意图.
Sun Java Compiler拒绝声明StrangeSubInner:
Test.java:32: type parameter java.lang.String is not within its bound
protected class StrangeSubInner extends Base<String>.BaseInner<String> {}
^
Run Code Online (Sandbox Code Playgroud)
显然,编译器并不是简单地检查类型参数来对抗内部的超类'类型参数绑定,就像eclipse那样.在这种情况下,我认为这是正确的做法,因为声明显然是不安全的.但是,Sun编译器同样拒绝以下声明,即使它是可证明类型安全的:
class StrangeSub extends Base<Integer> {
protected class StrangeSubInner extends BaseInner<Integer> {}
}
Run Code Online (Sandbox Code Playgroud)
我的预感是,验证这种菱形类型限制的一致性超出了Sun编译器的能力,因此这些结构被简单地拒绝了.
要解决这个限制,我首先尝试去掉类型参数CompoundIterator.
| 归档时间: |
|
| 查看次数: |
2123 次 |
| 最近记录: |