这个Java字符串数组声明出了什么问题?非常奇怪



我有三种不同的方法来用Java声明我的字符串数组。一个一直在工作,但另两个只根据它们的写作顺序工作。

在第一个版本中,方法2不起作用,但方式3起作用。

public class weirdStringArray {
String [] method1 = new String [] {"one","two","three"}; //<------ Works no matter where it's placed
String [] method2;       //<------ "Syntax error on token ";", { expected after this token"
method2 = new String[3]; //  Doesn't work in this postion
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
String [] method3 = new String[3]; //<-------  No issue, works fine in this position
method3[0] = "one";                
method3[1] = "two";
method3[2] = "three";
} // <----- Syntax error, insert "}" to complete ClassBody (but it does seem to complete ClassBody...?)

但是,转换位置和工作声明也会互换。看,现在方法2有效,但方式3无效。

public class weirdStringArray {
String [] method1 = new String [] {"one","two","three"};
String [] method3 = new String[3]; //<------ "Syntax error on token ";", { expected after this token"
method3[0] = "one";               //  Doesn't work in this postion
method3[1] = "two";
method3[2] = "three";
String [] method2; //<---------- Put it in a different place and it works
method2 = new String[3]; 
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
} // <----- Syntax error, insert "}" to complete ClassBody (but it does seem to complete ClassBody...?)

这里可能发生了什么?为什么订单会有什么不同?2号位发生了什么?顺便说一句,如果我删除第一个工作表单:,那没有什么区别

public class weirdStringArray {
//String [] method1 = new String [] {"one","two","three"};
String [] method2;        //<------ "Syntax error on token ";", { expected after this token"
method2 = new String[3]; //  Doesn't work in this postion 
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
String [] method3 = new String[3]; //<-------  No issue, works fine in this position
method3[0] = "one";               
method3[1] = "two";
method3[2] = "three";
} // <----- Syntax error, insert "}" to complete ClassBody (but it does seem to complete ClassBody...?)

试着让它像你想要的那样工作:

public class weirdStringArray {
String [] method1 = new String [] {"one","two","three"}; //<-- Works no matter where it's placed, because this is a valid one line initialisation
String [] method2;
{
// We gave it the '{' the compiler asked for …
method2 = new String[3];
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
}
String [] method3 = new String[3];
{
method3[0] = "one";                
method3[1] = "two";
method3[2] = "three";
} // <-- … and this is the missing '}'
}

这些"{…}"块是初始化程序块,更为人所知/更经常在其静态变体中使用,如static final属性的"static {…}"。这是因为这些初始化程序中的代码通常更好地放在构造函数中。

使用这些初始化程序的优点是它们在所有构造函数之前执行,缺点是它们在全部构造函数之前执行。当你玩final属性时最能看到…

它们适用于所有恒定的初始化,如这里的示例,以及其他类型的(潜在的(从未失败的初始化。应该避免从这里调用非静态方法,并且调用当前类的非静态方法根本不起作用(this尚未初始化,因为您当前正在初始化它…(。

类主体中不允许使用这些类型的语句。首先将它们包裹在方法体中。

除了初始化它之外,如果实例属性位于方法或构造函数的"外部",则不能对其执行任何操作(无论它是数组还是其他任何操作(。这就是你想要做的:

public class weirdStringArray {
String[] method1 = new String[] {"one", "two", "three"};
String[] method2 = new String[3];
String[] method3 = new String[3];
public weirdStringArray() {
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
method3[0] = "one";
method3[1] = "two";
method3[2] = "three";
}
}

或者,您也可以使用初始化块:

public class weirdStringArray {
// this way also works, it counts as initialization
String[] method1 = {"one", "two", "three"};
String[] method2 = new String[3];
{
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
}
String[] method3 = new String[3];
{
method3[0] = "one";
method3[1] = "two";
method3[2] = "three";
}
}

注意,除了实例化之外,您不能将代码放在类的主体中。检查以下代码以获取示例:

public class weirdStringArray {
String[] method1 = new String[] { "one", "two", "three" };
{
String[] method2;
method2 = new String[3];
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
String[] method3 = new String[3];
method3[0] = "one";
method3[1] = "two";
method3[2] = "three";
String[] method4;
method4 = new String[3];
method4[0] = "one";
method4[1] = "two";
method4[2] = "three";
}
public static void main(String[] args) {
String[] method2;
method2 = new String[3];
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";
String[] method3 = new String[3];
method3[0] = "one";
method3[1] = "two";
method3[2] = "three";
String[] method4;
method4 = new String[3];
method4[0] = "one";
method4[1] = "two";
method4[2] = "three";
}
}

这段代码编译起来没有问题,因为我放在方法外部的任何代码都是用于初始化的。如果我从类主体中的初始化代码中删除{}边界,代码将无法编译。有关详细信息,请参阅"初始化实例成员"部分。

TL;DR:在函数内移动整个代码块;这个问题将立即不复存在。



在方法/函数体之外,对变量唯一能做的就是初始化它,但即使这样,也需要在声明变量的同一行进行初始化。您面临这个问题是因为您试图在功能块之外执行实际操作。让我们逐一看一下每种方法。。。

第一种方法:

String [] method1 = new String [] {"one","two","three"};

上面的方法工作得很好,因为您同时执行声明和初始化。这里没有违反任何规则。

第二种方法:

String [] method2;       //<------ "Syntax error on token ";", { expected after this token"
method2 = new String[3]; //  Doesn't work in this postion
method2[0] = "one";
method2[1] = "two";
method2[2] = "three";

在第二行,您正在对上一行中声明的变量执行操作。这不能在函数之外完成。因此,出现了错误。

第三种方法:

String [] method3 = new String[3]; //<-------  No issue, works fine in this position
method3[0] = "one";                
method3[1] = "two";
method3[2] = "three";

第三个例子预计效果良好。原因如下:第一行表示声明和初始化变量的有效方式。即使后面的行是数组元素初始化,它们仍然被视为初始化变量的有效方式,因为在这种情况下,数组元素被视为独立的实体。



请记住,这里的关键点是确保所有声明后的代码都封装在方法/函数体中。

如果赋值操作不像method2和method3那样由单行组成,则应该将其放入函数体中。Java不允许这样做。

最新更新