以下是三个SSCCE,我相信它应该编译并且行为相同。我唯一要改变的是第一行“跑”。
图1
public class FinalExperiment {
private TinyThing thing;
public static void main(String[] args) {
FinalExperiment instance = new FinalExperiment();
instance.run();
}
public void run() {
final TinyThing thing = new TinyThing();
System.out.println("Got a thing here: " + thing);
}
private static class TinyThing {
public TinyThing() {}
public String toString() { return "Hello!"; }
}
}
这有效;它成功编译,并打印:“有一件事:你好!”
图表2
public class FinalExperiment {
private TinyThing thing;
public static void main(String[] args) {
FinalExperiment instance = new FinalExperiment();
instance.run();
}
public void run() {
final TinyThing otherThing = thing;
System.out.println("Got a thing here: " + otherThing);
}
private static class TinyThing {
public TinyThing() {}
public String toString() { return "Hello!"; }
}
}
这有效;它编译成功,并打印:“有一件事:null”
图3
public class FinalExperiment {
private TinyThing thing;
public static void main(String[] args) {
FinalExperiment instance = new FinalExperiment();
instance.run();
}
public void run() {
final TinyThing thing = thing;
System.out.println("Got a thing here: " + thing);
}
private static class TinyThing {
public TinyThing() {}
public String toString() { return "Hello!"; }
}
}
使用此消息无法编译:
FinalExperiment.java:10: error: variable thing might not have been initialized
final TinyThing thing = thing;
^
1 error
为什么呢?图表2和图3之间的唯一区别是我在thing
方法中隐藏了run
。似乎编译器不应该更简单地关注,因为正在发生阴影。
答案 0 :(得分:5)
是的,图3中出现了阴影,但实际上您正在尝试声明final
变量,然后将其分配给自身。
final TinyThing thing = thing; // Assign to self!
尚未为其分配值,因此您会收到编译器错误,表明它未初始化。无论局部变量thing
是否为final
,都会发生这种情况。
要引用实例变量,请使用this
。
final TinyThing thing = this.thing; // Bypass shadowing.
这会编译并产生与图表2相同的输出:
Got a thing here: null
此示例无法以相同方式编译,例如:
public class SelfDefineExample {
public static void main(String[] args) {
int i = i;
}
}
答案 1 :(得分:1)
执行final TinyThing thing = thing
时,您会引用尚未初始化的自变量。
您可以通过final TinyThing thing = this.thing;
哪个会输出
在这里有一件事:null
请注意,final
关键字不会改变此处的行为。
这与阴影无关,您可以使用任何其他值进行测试。
例如:Object a = a
会出现同样的错误。
答案 2 :(得分:1)
变量属于他们自己定义的范围。这样:
int i = i;
尝试使用自己的值初始化变量。但它没有价值,因为它尚未初始化!因此错误。