Следующий код компилируется в Java 1.6, но не компилируется в Java 1.7. Зачем?Почему этот код компилируется в Java 1.6, но не в Java 1.7?
Соответствующая часть кода является ссылкой на личное поле данных. Ссылка находится внутри того же класса, в котором поле определено, и поэтому кажется законным. Но это происходит с помощью типично типизированной переменной. Этот код - урезанный пример, основанный на классе из собственной библиотеки, - работал в 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;
}
}
Compiler выход:
> 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
Добавление. Такая же проблема возникает, если ссылка относится к частному методу вместо частной переменной-члена. Это работает в 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;
}
}
Compiler выход:
> 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);
^
Я бы предложил декомпилировать оба сгенерированных файла класса, тогда разница должна быть очевидной. – Landei
@ Landei В случае с 1.7 нет файла сгенерированного класса, поскольку компилятор отказывается его скомпилировать. –