簡體   English   中英

Java中的Try-Catch語句

[英]Try-Catch statements in Java

更新:感謝關於保持代碼SSCCE的建議。 就像我說的,這是我第一次在這里發帖。 我下次肯定會花時間確保代碼在我下次發布之前已經充分調整。


所以我正在為我的計算機科學課寫一個程序,並且遇到一個我無法弄清楚的奇怪問題。 我嘗試通過使用try / catch語句來阻止無效的數據類型輸入,然后它可能會結束並結束整個程序,從而使我的程序健壯,但它似乎不起作用。 輸入無效數據類型時,程序結束時不會在窗口中顯示任何Java的標准錯誤消息。 我不知道為什么會這樣,但我認為我錯誤地使用了try / catch語句。 以下是我的程序的兩個類:

/* 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;
     }
   }
 }

請注意,此程序存在一個我似乎無法解決的問題。 出於某種原因,每次用戶在菜單選擇提示下輸入無效數據類型時,程序結束(盡管沒有拋出任何錯誤)。

當您使用try-catch塊時,您實際上是在告訴編譯器將負責顯示錯誤消息 - 不會顯示內置消息。 相反,將顯示您在catch語句中包含的任何錯誤提示。

當我運行你的程序時,我看到你的錯誤消息,但沒有內置的Java錯誤消息; 這應該是怎么回事。 實際上,錯誤正在被拋出 - 但是你正在捕獲它們,因此Java不會在控制台上顯示默認消息。

關於你在課程結束時的評論:

如果用戶在菜單提示符處輸入了錯誤的數據類型,請查看正在發生的情況; menuItem仍為零。 因此,所有if語句都評估為false。 因此,else語句運行,終止程序。

其他答案解釋了為什么你沒有得到你期望的輸出。 我還想做一些重要的編程錯誤:

1)不要像那樣捕捉Exception

當您捕獲Exception您將捕獲可能由代碼拋出的Exception每個可能子類型。 在您的情況下,您顯然希望拋出InputMismatchException ,但nextXxx方法也可以拋出其他異常,例如NoSuchElementExceptionIllegalStateException 然后還有其他的可能性,如NullPointerException ,這將指示一個錯誤。

您應該明確地捕獲並處理您期望的異常,並將其他異常留給更通用的意外異常處理。

2)打印出Exception錯誤消息

它將為您提供實際錯誤的詳細信息; 例如

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

事實上,它是一個例外是意外的,打印或記錄異常的堆棧跟蹤是一個很好的想法,這樣你(或必須處理用戶錯誤報告的人)可以弄清楚實際發生了什么。

3)當setter的驗證失敗時,拋出異常:

你的二傳手做了這樣的事情:

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

問題有三個:

  • 安裝者通常不會返回任何東西。 這不是正常的習語。
  • 如果方法的調用者沒有檢查你的setter返回false,則不會注意到set操作沒有發生。
  • 沒有任何告知的原因設置操作失敗。

寫這樣:

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梯形圖的底部,然后點擊最后的休息時間。

只需在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;
}

因為您允許程序在捕獲異常后繼續執行,該異常將暫停您的程序。

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM