简体   繁体   English

未检测到循环中的初始化变量

[英]Initialized variables in loops not detected

I have this piece of code我有这段代码

    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 **** ");
    }

and I attempted to create new objects using the p4name, p5name variable我尝试使用 p4name, p5name 变量创建新对象

    Player p4 = new Player(p4name);
    Player p5 = new Player(p5name);

but the cmd said that p4name, p5name is not initialized.但是cmd说p4name,p5name没有初始化。 Is it because it was initialized in the if/else?是因为它是在 if/else 中初始化的吗? Is there any possible ways to overcome this without having to continue the rest of my code in the loop?是否有任何可能的方法来克服这个问题,而不必在循环中继续我的代码的 rest?

I would suggest to extract the following method:我建议提取以下方法:

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 **** ");
}

Typically, one should not pass a boolean as a parameter of a method but here IMO it is acceptable:通常,不应将 boolean 作为方法的参数传递,但在这里 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
    }

        

Most answers so far are suggesting you initialize these variables, and they are all bad advice .到目前为止,大多数答案都建议您初始化这些变量,它们都是不好的建议

You WANT to leave those variable uninitialized.希望保留这些变量未初始化。 The advice to pre-initialize them to a value are misleading and bad code style.将它们预初始化为一个值的建议是误导和糟糕的代码风格。

Let me first explain that bombshell before I explain what you should be doing in this case.在我解释在这种情况下你应该做什么之前,让我先解释一下这个重磅炸弹。

Why initializing locals is bad in cases like these为什么在这种情况下初始化本地人很糟糕

Presumably, if you ever get to the place where you execute p5 = new Player(p5Name) , and p5Name has never been set to any value yet, then you've actually got a bug in your program.据推测,如果您到达执行p5 = new Player(p5Name)的地方,并且 p5Name 尚未设置为任何值,那么您的程序实际上存在错误。 You do not want a player whose name is the empty string or a blank space.您不想要名称为空字符串或空格的玩家。

It is always better that bugs manifest as compilation errors: This means you cannot possibly ship your code with the bug (good thing), the editor will show a red wavy underline precisely at the location where you programmed it (fantastic), and you will be made aware of the fact that you have a bug as you type (marvellous).错误显示为编译错误总是更好:这意味着您不可能将带有错误的代码发布(好事),编辑器将在您编写它的位置精确地显示红色波浪下划线(太棒了),您将请注意您在键入时遇到错误的事实(了不起)。 Leaving the local variable unset gets you exactly this behaviour, which is why it's good to leave them unset.不设置局部变量会让你得到这种行为,这就是为什么最好不设置它们。 You want the compiler to check that all possible code paths initialize this variable / that all code paths where you end up using p5Name are only reachable via a route that also ends up setting p5Name before you use it.希望编译器检查所有可能的代码路径是否初始化此变量/您最终使用p5Name的所有代码路径只能通过在您使用它之前也最终设置p5Name的路径访问。

Contrast to the other option (just initialize them to some throw-away value, like the empty string or a space), which is where the line with the problem (namely, Player p5 = new Player(p5Name) isn't actually where the bug lies (because the bug lies in the control structure above that which has a path where p5Name never gets set), you won't know about the bug until you do a full test run, and a test may not even catch it.与另一个选项相比(只需将它们初始化为一些一次性值,例如空字符串或空格),这是有问题的行(即Player p5 = new Player(p5Name)实际上不是错误所在(因为错误位于控制结构上方的控制结构中,该结构具有永远不会设置 p5Name 的路径),在您进行完整的测试运行之前,您不会知道该错误,并且测试甚至可能无法捕获它。

How to do it right如何正确地做

Draw out your control structure as a tree, and figure out which case(s) lead to p5Name being unset.将你的控制结构画成一棵树,并找出哪些情况会导致 p5Name 未设置。 Then add cases to it, or if you feel that all cases are covered, update the code so the compiler follows along with you.然后向其中添加案例,或者如果您认为涵盖了所有案例,请更新代码,以便编译器跟随您。

In this case, in your pasted code, if there is any tie, then p4Name and p5Name are unset - and presumably you never wanted that to happen.在这种情况下,在您粘贴的代码中,如果有任何平局,则p4Namep5Name设置- 大概您不希望发生这种情况。

It is not clear from your paste what is supposed to happen then, but there are 2 obvious answers that come to mind:从您的粘贴中不清楚当时应该发生什么,但有两个明显的答案浮现在脑海:

  1. Whatever code creates p4 and p5 makes no sense in case there are ties between p1/p2/3, and should therefore never run.如果 p1/p2/3 之间存在联系,则无论创建 p4 和 p5 的代码都没有任何意义,因此不应运行。 If this is the case, your it is a tie!如果是这样的话,你的就是平局! block of code should use control flow to ensure that code then does not run.代码块应该使用控制流来确保代码不会运行。 Either return in the block, or make a method that creates p4/p5, which is only called from the non-it-is-a-tie blocks.要么在块中return ,要么创建一个创建 p4/p5 的方法,该方法仅从非它是一个关系块中调用。

  2. The code that creates p4 and p5 can run just fine even in case of ties.即使在平局的情况下,创建 p4 和 p5 的代码也可以正常运行。 If this is what you intended, then update your It is a tie!如果这是您的意图,请更新您的It is a tie! code block to set p4Name and p5Name to something sensible.将 p4Name 和 p5Name 设置为合理的代码块。 Possibly just flip a coin, or just pick one of the pX objects that are involved in the tie and christen them as the value for p4Name and p5Name.可能只是掷硬币,或者只是选择与领带相关的 pX 对象之一,并将它们命名为 p4Name 和 p5Name 的值。

... but there are always exceptions ...但总有例外

it is possible that your eyeballs and brain can figure out that it is impossible for a line that uses some local variable x to ever execute for a code path where x is unset, but, that the compiler isn't as smart as you are, and will still complain.您的眼球和大脑可能会发现,使用某些局部变量x的行不可能永远执行未设置x的代码路径,但是编译器不如您聪明,并且仍然会抱怨。

Usually, it is then better to refactor your code so that the compiler does figure it out.通常,最好重构您的代码,以便编译器能够弄清楚。 Occasionally, however, that does more harm than good (programming, in the end, requires a modicum of experience about how to write maintainable code, styleguides and rules of thumb are merely guidelines, not hard rules, and you'll never get to optimal maintainable code solely by aggressively applying a wide array of style rules no matter how much you invest in writing good style rules, programming just isn't that easy.), If that is the case, then and only then, sure.然而,有时这弊大于利(编程最终需要一点关于如何编写可维护代码的经验,样式指南和经验法则只是指导方针,而不是硬性规则,你永远不会达到最佳状态仅通过积极地应用广泛的样式规则来维护代码,无论您在编写良好的样式规则方面投入多少资金,编程都不是那么容易。),如果是这样,那么只有那时,当然。 init that variable to a throwaway, But know that you are missing out on compiler-checked bug-finding.将该变量初始化为一次性,但要知道您错过了编译器检查的错误发现。 which is a shame: You're basically saying, "The loss of compiler-check here is an evil. but it is the lesser evil compared to how ugly this code is going to get if I attempt to rewrite it so that compiler can figure out that there is no code path where I end up accessing it in an uninitialized state".真可惜:你基本上是在说,“这里失去编译器检查是一种邪恶。但与我尝试重写它以便编译器能够计算出这段代码的丑陋相比,它是一种较小的邪恶。没有代码路径可以让我最终以未初始化的状态访问它”。

Yeah.是的。 You need to initialize it to something(blank or null) outside of the if clause.您需要将其初始化为 if 子句之外的某些内容(空白或 null)。 Below change would work.以下更改将起作用。

String p4name = "";
String p5name = "";
if(p1score > p2score && p1score > p3score){

You forgot to initialize the variables, this will give you an error message you need to assign a value to the strings, so the strings are not null.您忘记初始化变量,这会给您一个错误消息,您需要为字符串赋值,因此字符串不是 null。 here is the code you need to implement:这是您需要实现的代码:

String p4name = " ";
String p5name = " ";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM