Java 为什么两个程序有前向引用错误,而第三个程序没有?
以下内容未编译,给出“非法转发引用”消息:Java 为什么两个程序有前向引用错误,而第三个程序没有?,java,static,instance,forward,Java,Static,Instance,Forward,以下内容未编译,给出“非法转发引用”消息: class StaticInitialisation { static { System.out.println("Test string is: " + testString); } private static String testString; public static void main(String args[]) { new StaticInitialisat
class StaticInitialisation {
static
{
System.out.println("Test string is: " + testString);
}
private static String testString;
public static void main(String args[]) {
new StaticInitialisation();
}
}
class InstanceInitialisation2 {
private String testString1;
{
testString1 = testString2;
}
private String testString2;
public static void main(String args[]) {
new InstanceInitialisation2();
}
}
但是,以下内容不适用:
class InstanceInitialisation1 {
{
System.out.println("Test string is: " + this.testString);
}
private String testString;
public static void main(String args[]) {
new InstanceInitialisation1();
}
}
但以下内容未编译,给出“非法转发引用”消息:
class StaticInitialisation {
static
{
System.out.println("Test string is: " + testString);
}
private static String testString;
public static void main(String args[]) {
new StaticInitialisation();
}
}
class InstanceInitialisation2 {
private String testString1;
{
testString1 = testString2;
}
private String testString2;
public static void main(String args[]) {
new InstanceInitialisation2();
}
}
为什么StaticInitialization和InstanceInitialization2不编译,而InstanceInitialization1编译?这在JLS的一节中介绍: 有时,即使这些类变量在范围内(§6.3),但其声明在使用后以文本形式出现的类变量的使用受到限制。具体而言,如果以下所有条件均为真,则为编译时错误:
- 类或接口C中的类变量声明在使用类变量后以文本形式出现
- 在C的类变量初始值设定项或C的静态初始值设定项中使用一个简单的名称
- 使用不在作业的左侧
- C是包含该用法的最内层类或接口
- 类或接口C中实例变量的声明在使用实例变量后以文本形式出现
- 在C的实例变量初始值设定项或C的实例初始值设定项中使用一个简单的名称
- 使用不在作业的左侧
- C是包含该用法的最内层类或接口
this
。这意味着它不符合上面引用的第二个列表中的第二个项目符号,因此没有错误
如果将其更改为:
System.out.println("Test string is: " + testString);
。。。那么它就不会编译了
或者相反,您可以将静态初始值设定项块中的代码更改为:
System.out.println("Test string is: " + StaticInitialisation.testString);
奇怪,但事情就是这样。这里我们要了解的是,在第二个代码段中,您使用的是块和这个关键字
让我们看看这两个例子,我想这会让你明白
public class InstanceAndSataticInit {
{
System.out.println("Test string is (instance init): " + this.testString);
}
static{
System.out.println("Test string is (static init ): " + InstanceAndSataticInit.testStringStatic);
}
public static String testStringStatic="test";
public String testString="test";
public static void main(String args[]) {
new InstanceAndSataticInit();
}
}
输出:
Test string is (static init ): null
Test string is (instance init): null
及
输出:
Test string is (static init ): test
Test string is (instance init): test
所以你可以说序列是这样的
静态初始化
和实例初始化2
但如果您的第二个工作示例
实例初始化1
使用这个关键字,实际上是在帮助编译器忽略文本层次结构。在我的第一个示例中调用InstanceAndSataticInit.testStringStatic
时,在static
的情况下也会发生同样的事情InstanceAndSataticInit原因很简单-分析和禁止所有正向引用太昂贵或不可能。e、 g
{
print( getX(); ); // this.x
print( that().x ); // this.x
}
int x;
int getX(){ return x; }
This that(){ return this; }
该规范决定禁止一些简单的案例,以表明程序员的常见错误
另请参见如果将第三个代码段更改为testString1=this.testString2,则第三个代码段可以工作
这是我第一次在Java类中看到一个代码块,它不是ctor、静态ctor或方法的一部分。我很想知道它是什么,它是怎么通过编译的,什么时候通过的executed@sharonbn:它们是实例初始值设定项或静态初始值设定项,分别在JLS的第8.6节和第8.7节中描述。我来这里是因为你的推特,你得到了我的+1,但这是@bayou.io链接。@MarkHurd:是的,这对我来说是新的:)