简体   繁体   English

Java中的Try-Catch语句

[英]Try-Catch statements in Java

UPDATE: Thanks for the advice about keeping codes SSCCE. 更新:感谢关于保持代码SSCCE的建议。 Like I said, this is my first time posting here. 就像我说的,这是我第一次在这里发帖。 I'll definitely take the time next time to make sure the code is sufficiently trimmed down before I post here next time. 我下次肯定会花时间确保代码在我下次发布之前已经充分调整。


So I'm writing a program for my computer science class, and having a strange problem that I can't figure out. 所以我正在为我的计算机科学课写一个程序,并且遇到一个我无法弄清楚的奇怪问题。 I tried to make my program robust by using try/catch statements to stop invalid data type input before it could foul up and end the entire program, but it doesn't seem to be working. 我尝试通过使用try / catch语句来阻止无效的数据类型输入,然后它可能会结束并结束整个程序,从而使我的程序健壮,但它似乎不起作用。 When an invalid data type is entered, the program ends without displaying any of Java's standard error messages in the window. 输入无效数据类型时,程序结束时不会在窗口中显示任何Java的标准错误消息。 I have no idea why this is, but I assume I'm using the try/catch statements incorrectly. 我不知道为什么会这样,但我认为我错误地使用了try / catch语句。 Here are the two classes for my program: 以下是我的程序的两个类:

/* The core class for the finance calculations to be done in the FinanceApp class. */

public class FinanceCore{
  // Instance variables
  int numYears;
  double principal;
  double interestRate;
  double balance;

  public FinanceCore(){
    numYears = 0;
    principal = 0;
    interestRate = 0;
    balance = 0;
  }

  // Mutator methods that return boolean values depending on whether the input was valid or not
  public boolean setYears(int y){
    if(y >= 0){
      numYears = y;
      return true;
    }
    else return false;
  }

  public boolean setPrincipal(double p){
    if(p >= 0){
      principal = p;
      balance = principal;
      return true;
    }
    else return false;
  }

  public boolean setInterestRate(double ir){
    if(ir >= 0 && ir <= 1){
      interestRate = ir;
      return true;
    }
    else return false;
  }

  // Two accessors
  public int getYears(){
    return numYears;
  }

  public double getPrincipal(){
    return principal;
  }

  // This method calculates and returns the balance at the end of each year
  public double plusYear(){
    balance = balance*(1+interestRate);
    return balance;
  }
}

/* This program recieves three pieces of data (interest rate, principal amount, number of years) and generates an output
* table that shows how much money will be in a fund with the given parameters at the end of every year. */

import java.util.Scanner;

public class FinanceApp{

  public static void main(String[]args){
    // First, we will declare our global variables, and set them to default values
    Scanner reader = new Scanner(System.in);
    FinanceCore account = new FinanceCore();
    int menuItem = 0;

    // Now, we'll greet the user (because we're friendly like that)
    System.out.println("Welcome! Please select a menu option below.");

    while(true){
      /* Now, our first user interface: a menu system that displays four options to the user arranged in
       * columns for aesthetic effect. This is accomplished using the printf method.
       */

      System.out.printf("%n%-20s%-20s%n%-20s%-20s%n%-20s%n",
        "Set Principal[1]","Set Interest Rate[2]","Set Timespan[3]","Calculate[4]","Quit[5]");

      System.out.print(": ");

      // Now we get the user input until it is valid, and catch and errors in input type
      try {
        menuItem = reader.nextInt(); 
      }
      catch(Exception e){
        reader.nextLine(); // Clear the input stream to avoid an infinite loop
        System.out.println("Please a valid number 1-5.");
      }

      // The code for setting the principal amount
      if(menuItem == 1){
      while(true){
        System.out.print("Please enter the principal investment amount: ");

        try{
          if(account.setPrincipal(reader.nextDouble()));
          break;
        }
        catch(Exception e){
          reader.nextLine(); // Clear the input stream to avoid an infinite loop
          System.out.println("Please enter a valid dollar amount.");
        }
      }
    }
    // The code for setting the interest rate
    else if(menuItem == 2){
      while(true){
        System.out.print("Please enter the quarterly interest rate: ");
        try{
          if(account.setInterestRate(reader.nextDouble()));
          break;
         }
         catch(Exception e){
           reader.nextLine(); // Clear the input stream to avoid an infinite loop
           System.out.println("Please enter a valid decimal number between 0 and 1 (inclusive).");
         }
       }
     }

     // The code for setting the number of years
     else if(menuItem == 3){
       while(true){
         System.out.print("Please enter the number of years the account will exist: ");
         try{
           if(account.setYears(reader.nextInt()));
           break;
         }
         catch(Exception e){
           reader.nextLine(); // Clear the input stream to avoid an infinite loop
           System.out.println("Please enter a valid integer value.");
         }
       }
     }

     // This part actually executes the calculation
     else if(menuItem == 4){
       System.out.printf("%-10s%-10s%n%-10d%-10.2f%n","YEAR","BALANCE",0,account.getPrincipal());
       int count = 1;
       for(int c = account.getYears(); c > 0; c--){
         System.out.printf("%-10d%-10.2f%n",count,account.plusYear());
         count++;
       }
     }

     // If the user enters any other number, the program quits
     else
       break;
     }
   }
 }

Note that there is one persistent problem with this program that I can't seem to fix. 请注意,此程序存在一个我似乎无法解决的问题。 For some reason, every time the user enters an invalid data type at the menu selection prompt, the program ends (although without any errors being thrown). 出于某种原因,每次用户在菜单选择提示下输入无效数据类型时,程序结束(尽管没有抛出任何错误)。

When you use a try-catch block, you're essentially telling the compiler that you're going to take care of displaying the error messages--no built-in messages will show. 当您使用try-catch块时,您实际上是在告诉编译器将负责显示错误消息 - 不会显示内置消息。 Instead, whatever error prompts you include in the catch statements will show. 相反,将显示您在catch语句中包含的任何错误提示。

When I run your program, I see your error messages, but no built-in Java error messages; 当我运行你的程序时,我看到你的错误消息,但没有内置的Java错误消息; this is how it should be. 这应该是怎么回事。 Really, the errors are being thrown--but you're catching them, so Java doesn't display the default message on the console. 实际上,错误正在被抛出 - 但是你正在捕获它们,因此Java不会在控制台上显示默认消息。

Regarding your comment at the end of the program: 关于你在课程结束时的评论:

Look at what's happening if the user enters an incorrect data type at the menu prompt; 如果用户在菜单提示符处输入了错误的数据类型,请查看正在发生的情况; menuItem is still zero. menuItem仍为零。 Thus, all the if statements evaluate to false. 因此,所有if语句都评估为false。 Thus, the else statement runs, which terminates the program. 因此,else语句运行,终止程序。

The other answers explain why you don't get the output you are expecting. 其他答案解释了为什么你没有得到你期望的输出。 I'd also like to important couple of programming mistakes that you are making: 我还想做一些重要的编程错误:

1) Don't catch Exception like that! 1)不要像那样捕捉Exception

When you catch Exception you catch each and every possible subtype of Exception that could be thrown by the code. 当您捕获Exception您将捕获可能由代码抛出的Exception每个可能子类型。 In your case, you are clearly expecting an InputMismatchException to be throw, but the nextXxx methods can also throw other exceptions such as NoSuchElementException or IllegalStateException . 在您的情况下,您显然希望抛出InputMismatchException ,但nextXxx方法也可以抛出其他异常,例如NoSuchElementExceptionIllegalStateException And then there is the possibility of others such as NullPointerException which would be indicative of a bug. 然后还有其他的可能性,如NullPointerException ,这将指示一个错误。

You should explicitly catch and handle the exceptions that you are expecting, and leave the others for more generic unexpected exception handling. 您应该明确地捕获并处理您期望的异常,并将其他异常留给更通用的意外异常处理。

2) Do print out the Exception error message 2)打印出Exception错误消息

It will give you details of the actual error; 它将为您提供实际错误的详细信息; eg 例如

  try {
    menuItem = reader.nextInt(); 
  }
  catch(InputMismatchException e){
    reader.nextLine(); // Clear the input stream to avoid an infinite loop
    System.out.println(e.getMessage());
    System.out.println("Please a valid number 1-5.");
  }

In fact, it an exception is unexpected, it is a GOOD IDEA to print out or log the exception's stack trace so that you (or the person who has to deal with error reports from users) can figure out what actually happened. 事实上,它是一个例外是意外的,打印或记录异常的堆栈跟踪是一个很好的想法,这样你(或必须处理用户错误报告的人)可以弄清楚实际发生了什么。

3) When a setter's validation fails, throw an exception: 3)当setter的验证失败时,抛出异常:

Your setters do this kind of thing: 你的二传手做了这样的事情:

public boolean setInterestRate(double ir){
    if(ir >= 0 && ir <= 1){
        interestRate = ir;
        return true;
    }
    else return false;
}

The problem is threefold: 问题有三个:

  • Setters don't normally return anything. 安装者通常不会返回任何东西。 It is not the normal idiom. 这不是正常的习语。
  • If the caller of the method doesn't check your setter has returned false, it won't notice that the set operation didn't happen. 如果方法的调用者没有检查你的setter返回false,则不会注意到set操作没有发生。
  • Nothing tells anything why the set operation failed. 没有任何告知的原因设置操作失败。

Write it like this: 写这样:

public boolean setInterestRate(double ir){
    if(ir >= 0 && ir <= 1){
        interestRate = ir;
    }
    else {
        throw new IllegalArgumentException(
            "Interest rate not between 0 and 1 (" + ir + ")");
    }
}

如果输入了一个无效的菜单项,你会得到menuItem = 0,它落在你的if梯形图的底部,然后点击最后的休息时间。

Just have a continue after the last statement of your catch block as follows; 只需在catch块的最后一个语句后继续,如下所示;

catch(Exception e){
reader.nextLine(); // Clear the input stream to avoid an infinite loop
System.out.println("Please a valid number 1-5.");
continue;
}

Because you allow the program to continue after catching the exception which halts your program as is progress along. 因为您允许程序在捕获异常后继续执行,该异常将暂停您的程序。

Hope this helps. 希望这可以帮助。

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

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