Java 如何在不不断关闭扫描的情况下制作一个静态扫描仪全局变量并在方法和主要方法中使用它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23586732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:10:00  来源:igfitidea点击:

How to make a ONE static scanner global variable without closing scan constantly and use it within methods and the main method?

javajdbcjava.util.scanner

提问by chanabos

I want to create a static scanner but i will like to put the try catch block around it so it can automatically close avoiding resources leaks and or this exception:

我想创建一个静态扫描器,但我想在它周围放置 try catch 块,以便它可以自动关闭以避免资源泄漏和/或此异常:

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Scanner.java:1585)
    at softwareEngineer.UserApp1.main(UserApp1.java:82)

Essentially I only want to create one static scanner declaration and use it throughout the main program and includes the static methods, at this point my code will require to create separate scanner for each method and you are force "scan.close()". the code below will recieve a exception handling error due to multiple scanner that was open and did not closein the program.

本质上,我只想创建一个静态扫描器声明并在整个主程序中使用它并包含静态方法,此时我的代码将需要为每个方法创建单独的扫描器,并且您必须强制执行“scan.close()”。由于多个扫描器在程序中打开但未关闭,下面的代码将收到异常处理错误。

I updated the code now i get null pointer exception

我现在更新了代码我得到空指针异常

import java.util.Scanner;

public class UserApp1 {
    static User currentCustomer = null; //single object
    static Scanner scan;
    //------------------------------------------------------- 
    // Create a list, then repeatedly print the menu and do what the 
    // user asks until they quit 
    //------------------------------------------------------- 
    public static void main(String[] args) {

     scan = new Scanner(System.in);)//scanner to avoid resource leak
            printMenu(); //print menu system from another function
            String choice = scan.nextLine(); //reads an input
            final String EXIT_now = "0";
            final String BACK = "back";
               while (!(choice.equalsIgnoreCase(EXIT_now))){

          switch(choice) {
                 case 1: break;
                             case 2: 
                               currentCustomer = loginInput();<---- errors happens here
                if(currentCustomer != null){
                    System.out.println("You have successfully login");
                }
                break;
                default: 
                    System.out.println("Sorry, invalid choice"); 
                    break;
                } //ends switch  
                printMenu(); //print menu system from another function
                choice = scan.nextLine(); //reads an input
            }//ends while 

    System.out.println("\t\t GoodBye!\n Thank you for trying our program.");           
        System.exit(0);
    }//ends main

    //---------------------------- 
    // Print the user's choices 
    //---------------------------- 
    public static void printMenu() { 
        System.out.println("\t\t The User Login System "); 
        System.out.println("\t\t ======================"); 
        System.out.println("The Menu Options:"); 
        System.out.println("1: Register an Account");
        System.out.println("2: Login to your Account");
        System.out.println("3: Reset Password");
        System.out.println("0: Quit/Exit ");

        System.out.println("Please enter your selection > "); 
    } //ends printMenu 

      public static User loginInput(){

         System.out.print( "\nFollow the Prompts to Log-In to your Account  \n ");
            System.out.print( "\nPlease enter your userid : \n ");
            String userid = scan.nextLine();// <---- errors happens here

            System.out.print( "\nPlease enter your password: \n ");
            String pass = scan.nextLine();

            currentCustomer = AccountList.loginUser(userid, pass);

            if (currentCustomer != null)
            {    
                return currentCustomer;
            }
            return null;
    }//ends loginInput

}//ends class*

回答by Rogue

You're using a try-with-resources, which will automatically close it when you finish the try block. Try setting it to a variable like so:

您正在使用 try-with-resources,它会在您完成 try 块时自动关闭它。尝试将其设置为如下变量:

public class MyClass {

    private static Scanner scan;

    public static void main(String[] args) {

        scan = new Scanner(System.in);

    }

}

Avoid making multiple scanners with the System.in input as well, as they will consume the stream and then you have an entirely different problem.

避免使用 System.in 输入制作多个扫描仪,因为它们会消耗流,然后您会遇到完全不同的问题。

回答by dimo414

Avoid using a static global Scanner at all, by passing the Scanner instance you want to work with to the relevant methods. Consider this simplified example:

通过将要使用的 Scanner 实例传递给相关方法,完全避免使用静态全局 Scanner。考虑这个简化的例子:

public static void main(String[] args) {
  try(Scanner in = new Scanner(System.in)) {
    String choice = in.nextLine().trim();
    if(choice.equals("1")) {
      doOp1(in);
    } else if(choice.equals("2")) {
      doOp2(in);
    } else {
      System.err.println("Invalid choice.  Goodbye.");
    }
  }
}

// Method takes an open, functioning Scanner as an argument, therefore
// it doesn't need to close it, or worry about where it came from, it
// simply uses it, does what it needs to do, and returns, trusting
// the caller to properly close the Scanner, since it opened it.
private void doOp1(Scanner in) {
  System.out.print("What is your name? ");
  String name = in.nextLine().trim();
  System.out.print("What is your favorite color? ");
  String color = in.nextLine().trim();
}

private void doOpt2(Scanner in) {
  ...
}

You want to compartmentalize your resources to ensure they are limited in scope and easy to close. Putting them in global state of any kind makes that very difficult. Instead, separate the opening and closing of the resource from the code using it. This sort of compartmentalization makes for much more maintainable, readable, and testable code.

您希望划分资源以确保它们的范围有限且易于关闭。将它们置于任何类型的全局状态都非常困难。相反,将资源的打开和关闭与使用它的代码分开。这种划分使得代码更易于维护、可读和可测试。

For instance, by passing an already open Scannerto your core business logic functions, you can mock a real user's behavior and create a test to ensure your code remains stable, by constructing a Scannerthat reads from a hard coded String, and passing that into your method, without needing to run the whole class and type in the behavior your testing manually again and again.

例如,通过Scanner向核心业务逻辑函数传递一个已经开放的函数,您可以模拟真实用户的行为并创建一个测试以确保您的代码保持稳定,方法是构造一个Scanner从硬编码字符串中读取的 ,并将其传递到您的方法中,而无需运行整个类并一次又一次地手动输入您的测试行为。