升级到Java 7后,generics类的types参数化字段变为不可见

现在, Eclipse Indigo SR1内置Java 7支持终于在一两周内出现,我将我的游乐场项目从Helios SR2 + JDK 1.6_23迁移到Indigo SR1 + JDK 1.7.0。 所有项目完全重build后,只有一个类未能编译。 下面这个类在Java 1.6(和1.5)上编译和运行得很好:

public abstract class Area<A extends Area<?>> implements Comparable<Area<?>> { private String name; private Area<?> parent; private Set<A> areas; protected Area(String name, A... areas) { this.name = name; this.areas = new TreeSet<A>(); for (A area : areas) { area.parent = this; this.areas.add(area); } } public Set<A> getAreas() { return areas; } // ... } 

线area.parent = this;parent上失败并出现以下错误:

区域<capture#1-of>父区不可见

在第一次怀疑Eclipse编译器之后,我试着用JDK 1.7.0中的普通的javac ,但是它给出了基本相同的错误,而来自JDK 1.6.0_23的javac成功没有错误。

将可见性更改为protected或缺省可解决问题。 但为什么完全超越了我。 我偷窥了http://bugs.sun.com ,但是我找不到任何类似的报告。

解决编译错误的另一种方法是用Area<?>replace类中所有使用的A声明(或者将其全部删除):

 public abstract class Area<A extends Area<?>> implements Comparable<Area<?>> { private String name; private Area<?> parent; private Set<Area<?>> areas; protected Area(String name, Area<?>... areas) { this.name = name; this.areas = new TreeSet<Area<?>>(); for (Area<?> area : areas) { area.parent = this; this.areas.add(area); } } public Set<Area<?>> getAreas() { return areas; } // ... } 

但这打破了吸气剂的目的。 例如下面的课程:

 public class Country extends Area<City> { public Country(String name, City... cities) { super(name, cities); } } 

我期望它返回Set<City> ,而不是Set<Area<?>>

Java 7中的哪个更改导致这些types参数化的字段变得不可见?

这似乎是一个javac6的错误,这是在javac7中修复的。

解决方法是上传:

 ((Area<?>)area).parent = this; 

这看起来很奇怪 – 为什么我们需要上演访问超级成员?

根本问题是,私有成员被明确排除在inheritance之外,因此A没有parent成员。 同样的问题可以通过一个非generics的例子来certificate。

错误消息“ 家长在区域中具有私人访问 ”并不十分准确,尽pipe在大多数情况下它可能是正确的。 然而,在这种情况下,这是误导性的,更好的消息将是“ A不从Areainheritance私有成员'父'


为了调查的兴趣,让我们对你的基于JLS的例子做一个完整的分析:

  • §4.4:绑定T & I1 ... In的typesvariablesX的成员是交集types的成员(§4.9) T & I1 ... In出现在声明typesvariables的地方。

  • §4.9:交集types与空类体,直接超类Ck和直接超接口IT1 , ..., ITn, ITn的类types(§8)具有相同的成员,在交集types出现的相同包中声明。

  • §6.6.1:如果成员或构造函数被声明为private,则只有在包含成员或构造函数声明的顶级类(§7.6)的主体内才允许访问。

  • §8.2:被声明为private的类的成员不会被该类的子类inheritance。

  • §8.5:一个类inheritance自它的直接超类,并直接超接口所有超类和非超类接口的非私有成员types,它们都可以在类中进行访问,并且不会被类中的声明所隐藏。