gpt4 book ai didi

java - 为什么这段代码可以在 Java 1.6 中编译,但不能在 Java 1.7 中编译?

转载 作者:太空狗 更新时间:2023-10-29 22:46:18 25 4
gpt4 key购买 nike

以下代码在 Java 1.6 中编译良好,但在 Java 1.7 中编译失败。为什么?

代码的相关部分是对私有(private)“数据”字段的引用。该引用来自定义该字段的同一个类,因此看起来是合法的。但它是通过一个通用类型的变量发生的。此代码 - 基于内部库中的类的精简示例 - 在 Java 1.6 中有效,但现在在 Java 1.7 中无效。

我不是在问如何解决这个问题。我已经这样做了。我试图找到一个解释,说明为什么这不再起作用。我想到了三种可能性:

  • 根据 JLS,此代码不合法,不应该编译(1.6 编译器中有一个错误,已在 1.7 中修复)
  • 根据 JLS,此代码合法,应该可以编译(1.7 编译器中引入了向后兼容性错误)
  • 此代码落入 JLS 中的灰色区域

Foo.java:

import java.util.TreeMap;
import java.util.Map;

public abstract class Foo<V extends Foo<V>> {

private final Map<String,Object> data = new TreeMap<String,Object>();

protected Foo() { ; }

// Subclasses should implement this as 'return this;'
public abstract V getThis();

// Subclasses should implement this as 'return new SubclassOfFoo();'
public abstract V getEmpty();

// ... more methods here ...

public V copy() {
V x = getEmpty();
x.data.clear(); // Won't compile in Java 1.7
x.data.putAll(data); // "
return x;
}

}

编译器输出:

> c:\tools\jdk1.6.0_11\bin\javac -version
javac 1.6.0_11

> c:\tools\jdk1.6.0_11\bin\javac c:\temp\Foo.java

> c:\tools\jdk1.7.0_10\bin\javac -version
javac 1.7.0_10

> c:\tools\jdk1.7.0_10\bin\javac c:\temp\Foo.java
Foo.java:18: error: data has private access in Foo
x.data.clear();
^
Foo.java:19: error: data has private access in Foo
x.data.putAll(data);
^
2 errors

附录。如果引用的是私有(private)方法而不是私有(private)成员变量,也会出现同样的问题。这适用于 Java 1.6 但不适用于 1.7。

Foo2.java:

import java.util.TreeMap;
import java.util.Map;

public abstract class Foo2<V extends Foo2<V>> {

private final Map<String,Object> data = new TreeMap<String,Object>();

protected Foo2() { ; }

// Subclasses should implement this as 'return this;'
public abstract V getThis();

// Subclasses should implement this as 'return new SubclassOfFoo();'
public abstract V getEmpty();

// ... more methods here ...

public V copy() {
V x = getEmpty();
x.theData().clear(); // Won't compile in Java 1.7
x.theData().putAll(data); // "
return x;
}

private Map<String,Object> theData() {
return data;
}

}

编译器输出:

> c:\tools\jdk1.6.0_11\bin\javac c:\temp\Foo2.java

> c:\tools\jdk1.7.0_10\bin\javac c:\temp\Foo2.java
Foo2.java:18: error: theData() has private access in Foo2
x.theData().clear();
^
Foo2.java:19: error: theData() has private access in Foo2
x.theData().putAll(data);
^

最佳答案

演示的问题似乎与 Oracle bug 6904536 中报告的行为相符。该错误已作为“不是问题”关闭,解释如下:

javac is behaving according to the JLS. See also 6558551, 6711619 and related JLS issue 6644562.

对应的JLS问题未解决,评论如下:

A simplified explanation for the membership of type variables is welcome. There is a general difficulty with private members of a type variable's bounds. Formally such members do not become members of the type variable itself, though javac and Eclipse traditionally made them members and code has come to rely on that:

class Test {
private int count = 0;
<Z extends Test> void m(Z z) {
count = z.count; // Legal in javac 1.6, illegal in javac 1.7 due to fix for 6711619
}
}

Peter submitted a similar test:

class A {
static class B { private String f; }

abstract static class Builder<T extends B> {
abstract T getB();

{
((B)getB()).f.hashCode();
getB().f.hashCode(); // error: f has private access in A.B
}

}
}

Since intersection types are constructed by inheritance, and private members are never inherited, it is tricky to re-specify intersection types to have private members. Nonetheless, it would be the compatible thing to do.

作为引用,JLS 的相关部分是 §4.4

编辑:

实际上,我在这里倾向于同意 JLS,因为当我们从图片中删除泛型时,它会与自身匹配。考虑这个例子:

static class Parent {

private int i;

void m(Child child) {
i = child.i; //compile error
}
}

static class Child extends Parent { }

child.i 不可见,因为对私有(private)成员的访问不是继承的。 Child 可以拥有自己的 i 而没有任何阴影这一事实使这一点更加明确:

static class Child extends Parent {
private int i; //totally fine
}

所以这将是一个罕见的向上转型的例子:

void m(Child child) {
i = ((Parent)child).i;
}

因此,考虑到 V 中的 Foo<V extends Foo<V>> 不一定是 Foo<V> 但可能是扩展 Foo<V> 的某种类型,因此在继承可访问性的情况下,JLS 在这里似乎是正确的。

关于java - 为什么这段代码可以在 Java 1.6 中编译,但不能在 Java 1.7 中编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15681444/

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