【问题标题】:Initialized variables in loops not detected未检测到循环中的初始化变量
【发布时间】:2021-06-11 10:04:40
【问题描述】:

我有这段代码

    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 中初始化的吗?是否有任何可能的方法来克服这个问题,而不必在循环中继续我的其余代码?

【问题讨论】:

    标签: java loops variables reference


    【解决方案1】:

    我建议提取以下方法:

    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
        }
    
            
    

    【讨论】:

      【解决方案2】:

      到目前为止,大多数答案都建议您初始化这些变量,它们都是不好的建议

      想要不初始化这些变量!将它们预初始化为一个值的建议具有误导性,并且代码风格不佳。

      让我先解释一下这个重磅炸弹,然后再解释在这种情况下你应该做什么。

      为什么在这种情况下初始化局部变量是不好的

      大概,如果你到达你执行p5 = new Player(p5Name) 的地方,并且 p5Name 还没有被设置为任何值,那么你的程序实际上有一个错误。你不想要一个名字是空字符串或空格的玩家。

      最好将错误显示为编译错误:这意味着您不可能将带有错误的代码发布(好事),编辑器将在您编写它的位置精确地显示红色波浪下划线(太棒了),并且您会在键入时意识到您有一个错误(奇妙)。不设置局部变量会让你得到这种行为,这就是为什么最好不设置它们。您想要编译器检查所​​有可能的代码路径是否初始化此变量/您最终使用 p5Name 的所有代码路径只能通过在您之前设置 p5Name 的路径访问使用它。

      与另一个选项对比(只需将它们初始化为一些一次性值,例如空字符串或空格),这就是问题所在行(即,Player p5 = new Player(p5Name) 实际上并不是错误所在(因为 bug 位于控制结构上方的控制结构中,其路径中 p5Name 永远不会被设置),在您进行完整的测试运行之前,您不会知道该 bug,并且测试甚至可能无法捕获它。

      如何正确处理

      将你的控制结构画成一棵树,并找出哪些情况会导致 p5Name 未设置。然后向其中添加案例,或者如果您认为涵盖了所有案例,请更新代码以便编译器跟随您。

      在这种情况下,在您粘贴的代码中,如果有任何平局,那么 p4Namep5Name未设置 - 大概您不希望发生这种情况。

      从您的粘贴中不清楚当时应该发生什么,但有两个明显的答案浮现在脑海:

      1. 如果 p1/p2/3 之间存在关联,则创建 p4 和 p5 的任何代码都没有意义,因此不应运行。如果是这种情况,您的是平局! 代码块应该使用控制流来确保代码不会运行。要么在块中return,要么创建一个创建 p4/p5 的方法,该方法只能从非它是一个关系块中调用。

      2. 创建 p4 和 p5 的代码即使在平局的情况下也可以正常运行。如果这是您想要的,那么更新您的 It is a tie! 代码块以将 p4Name 和 p5Name 设置为合理的值。可能只是掷硬币,或者只是选择与领带相关的 pX 对象之一,并将它们命名为 p4Name 和 p5Name 的值。

      ...但总有例外

      您的眼球和大脑可能会发现,对于未设置 x 的代码路径,使用某些局部变量 x 的行不可能执行,但是编译器不是t 和你一样聪明,但仍然会抱怨。

      通常,最好重构您的代码,以便编译器能够弄清楚。然而,有时这弊大于利(编程最终需要一点关于如何编写可维护代码的经验,样式指南和经验法则只是指导方针,而不是硬性规则,你永远不会达到最佳状态仅通过积极地应用广泛的样式规则来维护代码,无论您在编写良好的样式规则方面投入多少,编程都不是那么容易!)。如果是这种情况,那么并且只有这样,当然,将该变量初始化为一次性。但是要知道你错过了编译器检查的错误发现,这是一种耻辱。您基本上是在说:“这里失去编译器检查是一种邪恶,但与如果我尝试重写它以便编译器可以找出没有我最终在未初始化状态下访问它的代码路径”。

      【讨论】:

        【解决方案3】:

        你忘了初始化变量,这会给你一个错误信息 您需要为字符串赋值,因此字符串不为空。 这是您需要实现的代码:

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

        【讨论】:

          【解决方案4】:

          是的。您需要将其初始化为 if 子句之外的某些内容(空白或 null)。以下更改将起作用。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-24
            • 1970-01-01
            • 2015-01-19
            • 2012-01-02
            • 1970-01-01
            • 2011-04-02
            • 1970-01-01
            相关资源
            最近更新 更多