gpt4 book ai didi

java - 泛型类的类型参数化字段在升级到 Java 7 后变得不可见

转载 作者:IT老高 更新时间:2023-10-28 20:41:36 29 4
gpt4 key购买 nike

现在 Eclipse Indigo SR1内置 Java 7支持终于在一两周后结束了,我正在将我的 Playground 项目从 Helios SR2 + JDK 1.6_23 迁移到 Indigo SR1 + JDK 1.7.0。在完全重建所有项目后,只有一个类无法编译。以下类在 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 上失败并出现以下错误:

The field Area<capture#1-of ?>.parent is not visible

在首先怀疑 Eclipse 编译器之后,我尝试使用普通的 javac从 JDK 1.7.0 开始,但它给出了基本相同的错误,而 javac从 JDK 1.6.0_23 开始成功,没有错误。

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

修复编译错误的另一种方法是替换所有使用过的A Area<?> 类内的声明(或完全删除):

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;
}

// ...
}

但这破坏了 setter/getter 的目的。例如以下类:

public class Country extends Area<City> {

public Country(String name, City... cities) {
super(name, cities);
}

}

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

Java 7 中的哪些变化导致这些类型参数化的字段变得不可见?

最佳答案

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

解决方法是向上转换:

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

这看起来很奇怪——为什么我们需要向上转换才能访问父类(super class)中的成员?

根本问题是,私有(private)成员被明确排除在继承之外,因此 A 没有 parent 成员。同样的问题可以用一个非泛型的例子来证明。

错误消息“parent 在区域中有私有(private)访问权”不是很准确,但在大多数情况下可能没问题。但是在这种情况下,它会产生误导,更好的消息是“A 不会从 Area 继承私有(private)成员 'parent'


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

  • §4.4:类型变量 X 与绑定(bind) T & I1 ... In 的成员是交集类型的成员(§4.9) T & I1 ... In 出现在声明类型变量的位置。

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

  • §6.6.1:如果成员或构造函数被声明为私有(private),则当且仅当它出现在包含该成员或构造函数。

  • §8.2:声明为私有(private)的类的成员不会被该类的子类继承。

  • §8.5:一个类从它的直接父类(super class)和直接超接口(interface)继承父类(super class)和超接口(interface)的所有非私有(private)成员类型,这些类型和超接口(interface)都可以被类中的代码访问,并且不会被类中的声明隐藏。

关于java - 泛型类的类型参数化字段在升级到 Java 7 后变得不可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7719843/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com