未检测到循环中的初始化变量
Initialized variables in loops not detected
我有这段代码
String p4name;
String p5name;
if(p1score > p2score && p1score > p3score){
if(p2score > p3score){
p1.setWinner(true);
p2.setWinner(true);
p3.setWinner(false);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p2.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p2.getName();
}
else{
p1.setWinner(true);
p2.setWinner(false);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p3.getName();
}
}
else if(p2score > p1score && p2score > p3score){
if(p1score > p3score){
p1.setWinner(true);
p2.setWinner(true);
p3.setWinner(false);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p2.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p2.getName();
}
else{
p1.setWinner(false);
p2.setWinner(true);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p2.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p2.getName();
p5name = p3.getName();
}
}
else if (p3score > p1score && p3score > p2score){
if(p1score > p2score){
p1.setWinner(true);
p2.setWinner(false);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p3.getName();
}
else{
p1.setWinner(false);
p2.setWinner(true);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p2.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p2.getName();
p5name = p3.getName();
}
}
else {
System.out.println();
System.out.println();
System.out.println("**** It's a tie **** ");
}
我尝试使用 p4name、p5name 变量创建新对象
Player p4 = new Player(p4name);
Player p5 = new Player(p5name);
但是cmd说p4name,p5name没有初始化。是不是因为在if/else中初始化了?有没有可能的方法来克服这个问题,而不必在循环中继续我的其余代码?
是的。您需要将其初始化为 if 子句之外的内容(空白或空)。下面的更改将起作用。
String p4name = "";
String p5name = "";
if(p1score > p2score && p1score > p3score){
您忘记初始化变量,这会给您一条错误消息
您需要为字符串分配一个值,因此字符串不为空。
这是您需要实现的代码:
String p4name = " ";
String p5name = " ";
我建议提取以下方法:
public void setWinners(.. p1, boolean p1Win, .. p2, boolean p2Win, .. p3, boolean p3Win){
p1.setWinner(p1Win);
p2.setWinner(p2Win);
p3.setWinner(p3Win);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p2.getName() + " proceed to 2-Player phase **** ");
}
通常情况下,不应将布尔值作为方法的参数传递,但在这里 IMO 是可以接受的:
String p4name;
String p5name;
if(p1score > p2score && p1score > p3score){
p4name = p1.getName();
if(p2score > p3score){
setWinners(p1, true, p2, true, p3, false);
p5name = p2.getName();
}
else{
setWinners(p1, true, p2, false, p3, true);
p5name = p3.getName();
}
}
else if(p2score > p1score && p2score > p3score){
if(p1score > p3score){
setWinners(p1, true, p2, true, p3, false);
p4name = p1.getName();
}
else{
setWinners(p1, false, p2, true, p3, true);
p4name = p2.getName();
}
p5name = p2.getName();
}
else if (p3score > p1score && p3score > p2score){
if(p1score > p2score){
setWinners(p1, true, p2, false, p3, true);
p4name = p1.getName();
}
else{
setWinners(p1, false, p2, true, p3, true);
p4name = p2.getName();
}
p5name = p3.getName();
}
else {
System.out.println();
System.out.println();
System.out.println("**** It's a tie **** ");
return; // Exist the game
}
到目前为止,大多数答案都建议您初始化这些变量,它们都是糟糕的建议。
你想要让那些变量保持未初始化状态!将它们预初始化为一个值的建议具有误导性和错误的代码风格。
让我先解释一下那个重磅炸弹,然后再解释你在这种情况下应该做什么。
为什么在这些情况下初始化局部变量是不好的
据推测,如果您到达执行 p5 = new Player(p5Name)
的位置并且 p5Name 尚未设置为任何值,那么您的程序实际上存在错误。您不想要名称为空字符串或空白 space.
的玩家
Bug 表现为编译错误总是更好:这意味着你不可能将你的代码与 Bug 一起发送(好事),编辑器将在你编程的位置精确地显示红色波浪下划线(太棒了), 你会意识到你在输入时有一个错误(太棒了)。保留局部变量未设置会导致您出现这种行为,这就是为什么最好保留它们未设置的原因。您希望 编译器检查是否所有可能的代码路径都初始化此变量/您最终使用 p5Name
的所有代码路径只能通过最终设置的路由访问p5Name
在你使用它之前。
对比另一个选项(只需将它们初始化为一些一次性值,如空字符串或 space),这是有问题的地方(即 Player p5 = new Player(p5Name)
实际上不是 bug 所在的地方(因为 bug 位于控制结构之上,它有一条 p5Name 永远不会被设置的路径),在你做一个完整的测试之前你不会知道这个 bug 运行,测试甚至可能无法捕捉到它。
正确的做法
把你的控制结构画成一棵树,找出哪些情况导致 p5Name 被取消设置。然后向其中添加案例,或者如果您觉得涵盖了所有案例,请更新代码,以便编译器跟随您。
在这种情况下,在您粘贴的代码中,如果有任何平局,则 p4Name
和 p5Name
是 unset - 并且大概您从未想要那会发生。
从你的粘贴中看不出接下来会发生什么,但我想到了 2 个明显的答案:
任何创建 p4 和 p5 的代码都没有意义,以防 p1/p2/3 之间存在联系,因此永远不应 运行。如果是这种情况,您的 它是一个平局! 代码块应该使用控制流来确保代码然后不会 运行。在块中 return
,或者创建一个创建 p4/p5 的方法,该方法仅从非平局块中调用。
创建 p4 和 p5 的代码可以 运行 即使在关系相同的情况下也可以。如果这是您想要的,那么请更新您的 It is a tie! 代码块以将 p4Name 和 p5Name 设置为合理的值。可能只是掷硬币,或者只是选择一个参与平局的 pX 对象并将它们命名为 p4Name 和 p5Name 的值。
...但总有例外
您的眼球和大脑可能会发现使用某些局部变量 x
的行不可能在未设置 x
的代码路径中执行,但是, 编译器没有你聪明,还是会报错。
通常,最好重构您的代码,以便编译器能够解决问题。然而,有时这弊大于利(编程最终需要一些关于如何编写可维护代码的经验,风格指南和经验法则只是指南,而不是硬性规则,你永远不会达到最佳状态仅通过积极应用广泛的样式规则来维护代码,无论您在编写良好的样式规则方面投入多少,编程都不是那么容易!)。如果是这种情况,那么并且只有到那时,当然,将该变量初始化为一次性变量。但是要知道您错过了编译器检查的错误查找,这很遗憾。你基本上是在说:“这里丢失编译器检查是一种邪恶,但与如果我试图重写这段代码会让编译器发现没有我最终以未初始化状态访问它的代码路径。
我有这段代码
String p4name;
String p5name;
if(p1score > p2score && p1score > p3score){
if(p2score > p3score){
p1.setWinner(true);
p2.setWinner(true);
p3.setWinner(false);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p2.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p2.getName();
}
else{
p1.setWinner(true);
p2.setWinner(false);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p3.getName();
}
}
else if(p2score > p1score && p2score > p3score){
if(p1score > p3score){
p1.setWinner(true);
p2.setWinner(true);
p3.setWinner(false);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p2.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p2.getName();
}
else{
p1.setWinner(false);
p2.setWinner(true);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p2.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p2.getName();
p5name = p3.getName();
}
}
else if (p3score > p1score && p3score > p2score){
if(p1score > p2score){
p1.setWinner(true);
p2.setWinner(false);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p1.getName();
p5name = p3.getName();
}
else{
p1.setWinner(false);
p2.setWinner(true);
p3.setWinner(true);
System.out.println();
System.out.println();
System.out.println("**** " + p2.getName() + " and " + p3.getName() + " proceed to 2-Player phase **** ");
p4name = p2.getName();
p5name = p3.getName();
}
}
else {
System.out.println();
System.out.println();
System.out.println("**** It's a tie **** ");
}
我尝试使用 p4name、p5name 变量创建新对象
Player p4 = new Player(p4name);
Player p5 = new Player(p5name);
但是cmd说p4name,p5name没有初始化。是不是因为在if/else中初始化了?有没有可能的方法来克服这个问题,而不必在循环中继续我的其余代码?
是的。您需要将其初始化为 if 子句之外的内容(空白或空)。下面的更改将起作用。
String p4name = "";
String p5name = "";
if(p1score > p2score && p1score > p3score){
您忘记初始化变量,这会给您一条错误消息 您需要为字符串分配一个值,因此字符串不为空。 这是您需要实现的代码:
String p4name = " ";
String p5name = " ";
我建议提取以下方法:
public void setWinners(.. p1, boolean p1Win, .. p2, boolean p2Win, .. p3, boolean p3Win){
p1.setWinner(p1Win);
p2.setWinner(p2Win);
p3.setWinner(p3Win);
System.out.println();
System.out.println();
System.out.println("**** " + p1.getName() + " and " + p2.getName() + " proceed to 2-Player phase **** ");
}
通常情况下,不应将布尔值作为方法的参数传递,但在这里 IMO 是可以接受的:
String p4name;
String p5name;
if(p1score > p2score && p1score > p3score){
p4name = p1.getName();
if(p2score > p3score){
setWinners(p1, true, p2, true, p3, false);
p5name = p2.getName();
}
else{
setWinners(p1, true, p2, false, p3, true);
p5name = p3.getName();
}
}
else if(p2score > p1score && p2score > p3score){
if(p1score > p3score){
setWinners(p1, true, p2, true, p3, false);
p4name = p1.getName();
}
else{
setWinners(p1, false, p2, true, p3, true);
p4name = p2.getName();
}
p5name = p2.getName();
}
else if (p3score > p1score && p3score > p2score){
if(p1score > p2score){
setWinners(p1, true, p2, false, p3, true);
p4name = p1.getName();
}
else{
setWinners(p1, false, p2, true, p3, true);
p4name = p2.getName();
}
p5name = p3.getName();
}
else {
System.out.println();
System.out.println();
System.out.println("**** It's a tie **** ");
return; // Exist the game
}
到目前为止,大多数答案都建议您初始化这些变量,它们都是糟糕的建议。
你想要让那些变量保持未初始化状态!将它们预初始化为一个值的建议具有误导性和错误的代码风格。
让我先解释一下那个重磅炸弹,然后再解释你在这种情况下应该做什么。
为什么在这些情况下初始化局部变量是不好的
据推测,如果您到达执行 p5 = new Player(p5Name)
的位置并且 p5Name 尚未设置为任何值,那么您的程序实际上存在错误。您不想要名称为空字符串或空白 space.
Bug 表现为编译错误总是更好:这意味着你不可能将你的代码与 Bug 一起发送(好事),编辑器将在你编程的位置精确地显示红色波浪下划线(太棒了), 你会意识到你在输入时有一个错误(太棒了)。保留局部变量未设置会导致您出现这种行为,这就是为什么最好保留它们未设置的原因。您希望 编译器检查是否所有可能的代码路径都初始化此变量/您最终使用 p5Name
的所有代码路径只能通过最终设置的路由访问p5Name
在你使用它之前。
对比另一个选项(只需将它们初始化为一些一次性值,如空字符串或 space),这是有问题的地方(即 Player p5 = new Player(p5Name)
实际上不是 bug 所在的地方(因为 bug 位于控制结构之上,它有一条 p5Name 永远不会被设置的路径),在你做一个完整的测试之前你不会知道这个 bug 运行,测试甚至可能无法捕捉到它。
正确的做法
把你的控制结构画成一棵树,找出哪些情况导致 p5Name 被取消设置。然后向其中添加案例,或者如果您觉得涵盖了所有案例,请更新代码,以便编译器跟随您。
在这种情况下,在您粘贴的代码中,如果有任何平局,则 p4Name
和 p5Name
是 unset - 并且大概您从未想要那会发生。
从你的粘贴中看不出接下来会发生什么,但我想到了 2 个明显的答案:
任何创建 p4 和 p5 的代码都没有意义,以防 p1/p2/3 之间存在联系,因此永远不应 运行。如果是这种情况,您的 它是一个平局! 代码块应该使用控制流来确保代码然后不会 运行。在块中
return
,或者创建一个创建 p4/p5 的方法,该方法仅从非平局块中调用。创建 p4 和 p5 的代码可以 运行 即使在关系相同的情况下也可以。如果这是您想要的,那么请更新您的 It is a tie! 代码块以将 p4Name 和 p5Name 设置为合理的值。可能只是掷硬币,或者只是选择一个参与平局的 pX 对象并将它们命名为 p4Name 和 p5Name 的值。
...但总有例外
您的眼球和大脑可能会发现使用某些局部变量 x
的行不可能在未设置 x
的代码路径中执行,但是, 编译器没有你聪明,还是会报错。
通常,最好重构您的代码,以便编译器能够解决问题。然而,有时这弊大于利(编程最终需要一些关于如何编写可维护代码的经验,风格指南和经验法则只是指南,而不是硬性规则,你永远不会达到最佳状态仅通过积极应用广泛的样式规则来维护代码,无论您在编写良好的样式规则方面投入多少,编程都不是那么容易!)。如果是这种情况,那么并且只有到那时,当然,将该变量初始化为一次性变量。但是要知道您错过了编译器检查的错误查找,这很遗憾。你基本上是在说:“这里丢失编译器检查是一种邪恶,但与如果我试图重写这段代码会让编译器发现没有我最终以未初始化状态访问它的代码路径。