【问题标题】:Variable scope in try catch blocktry catch 块中的变量范围
【发布时间】:2014-11-08 20:34:19
【问题描述】:

我正在通过命令行创建一个用户界面,该界面将询问从 1 到 4 的选项,并且我想要进行错误检查。只允许 1 - 4 之间的整数。这是我到目前为止的代码。我希望该方法将 userInput 整数返回给另一个可以用它做一些事情的方法。

package contactmanager;

import java.util.InputMismatchException;
import java.util.Scanner;

/**
 *
 * @author andyjohnson
 */
public class UserInterface {

    public static Integer GetInput() {
        Scanner in = new Scanner(System.in);
        //Integer userInput;
        System.out.println("Welcome to the contact manager\nMake a selection below:");
        System.out.println("1)Display Contacts\n2)Add new business contact\n3)Add new personal contact\n4)Quit");
        try {
            Integer userInput = in.nextInt();
            if (userInput < 1 || userInput > 4) {
                System.out.println("Please enter a valid selection");
                UserInterface.GetInput();
            }

        } catch (InputMismatchException e) {
            e.getMessage();
            System.out.println("Please enter a valid selection");
            UserInterface.GetInput();
        }

        return userInput;

    }

}

我的 return 语句在 IDE 中带有下划线,告诉我它没有初始化。我想全局初始化它,但允许 try 语句更改值。我试过 this.userInput = userInput 但我不知道我的范围在哪里坏了。如何给 try 块全局范围?我是java新手,所以任何东西都有帮助。谢谢!

【问题讨论】:

    标签: java variables scope try-catch console-application


    【解决方案1】:

    您可以在 try-catch 块之外声明 userInput 变量:

    package contactmanager;
    
    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class UserInterface {
    
        public static Integer GetInput() {
            Scanner in = new Scanner(System.in);
            System.out.println("Welcome to the contact manager\nMake a selection below:");
            System.out.println("1)Display Contacts\n2)Add new business contact\n3)Add new personal contact\n4)Quit");
            Integer userInput = null;
            try {
                userInput = in.nextInt();
                if (userInput < 1 || userInput > 4) {
                    System.out.println("Please enter a valid selection");
                    UserInterface.GetInput();
                }
    
            } catch (InputMismatchException e) {
                e.getMessage();
                System.out.println("Please enter a valid selection");
                UserInterface.GetInput();
            }
    
            return userInput;
    
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      try-catch 块的作用域与仅在方法的其余部分内联编写代码不同。

      我认为您遇到的问题是在userInput 变量首先在try-catch 块内声明的这一行:

      Integer userInput = in.nextInt();
      

      这是一个问题的原因:

      考虑try-catch 块是否失败。那么什么会被退回呢?变量userInput 甚至还没有定义,所以Java 不知道要返回什么。

      修复相对简单。您只想将其移出try-catch 块,就像这样。那应该摆脱您的return 错误。我注意到你评论了这个变化。为什么?

      但我还有一个建议。你为什么打电话给UserInterface.GetInput()?为什么不让该方法接受有效输入的参数,并且在数据格式不正确时根本不调用它?你用它吗?这将消除对真正全局范围变量的需求。

      由于此方法的编写方式,它必须返回某种Integer,除非您编写它应该是该方法抛出一个在下游某处捕获的异常。

      我尝试进行一些我认为最有意义的修复:

      Scanner in = new Scanner(System.in);
      Integer userInput; // Integer representation of user input
      
      try {
          Integer a = in.nextInt(); // if a can be assigned to an Integer this line work
          if (a < 1 || a > 4) {
              // called if the input can be assigned to an Integer and is within the range
              userInput = a;
          }
      
      } catch (InputMismatchException e) {
          // otherwise the catch block is called
          System.out.println("Please enter a valid selection");
      }
      
      return userInput;
      

      也许您想在范围检查内调用UserInterface.GetInput()?希望这会有所帮助!

      编辑:使用哨兵标志而不是调用方法

      Scanner input = new Scanner(System.in);
      System.out.println("Please enter a valid Integer.  When done type DONE ");
      
      // this method will keep cycling until the String DONE is typed
      // you could make this condition whatever you want
      while (!input.hasNext("DONE")) {
      
          String a = input.next(); // gets the next item from the Scanner
      
          try {
              Integer b = Integer.parseInt(a); // tries to 'cast' the String to an Integer
      
              if (b < 1 || b > 4) {
                  System.out.println("Input is valid!");
              } else {
                  System.out.println("Input is invalid!");
              }
      
          } catch (NumberFormatException e) {
              System.out.println("Please enter a valid selection!");
          }
      }
      

      【讨论】:

      • 我需要按照规范再次调用 UserInterface.GetInput()。如果输入验证失败,程序需要再次给出菜单。我尝试了这个建议,但它似乎没有验证输入整数是 0 还是 5。输入像 foo 这样的字符串给了我 catch 语句中的代码。如果 try 验证失败或 catch 执行再次调用菜单方法的最佳方法是什么?规范说这应该在输入验证失败后为用户提供菜单。我想让 UserInterface 方法静态化,这样就不需要实例化了。
      • 我不知道您正在查看的“规范”中概述了哪些条件。我测试了这种方法,它似乎对我有用。我不明白UserInterface.GetInput() 是如何与它联系在一起的,因为你已经得到了输入。
      • 为了清楚起见,我在原始答案中添加了 cmets。
      • 如果输入失败,我需要请求正确的输入。最好的方法是再次调用整个方法,还是有更好的方法?基本上,在用户完成任何操作后,我需要它返回“主菜单”。
      • 哦,我现在明白了。您所描述的最好通过所谓的sentinel flag 来完成。等一下,让我编辑我的帖子。
      猜你喜欢
      • 2015-12-05
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      • 2012-07-24
      • 2019-08-02
      • 1970-01-01
      • 1970-01-01
      • 2011-07-25
      相关资源
      最近更新 更多