java的nextLine()的一個報錯引發的思考
寫在最前面:
晚上幫一位同學看一段程式碼,程式碼很入門,不過是java的,還好我也是懂java的男人,哼哼
程式碼如下,我做了一點調整,方便看輸出:
package Arithmetic; import java.util.Scanner; class PayCheck { public static void main(String args[]) { //user's input Scanner kbReader = new Scanner (System.in); String famName; String givName; double ratePay; int workHour; char charity; char tax; System.out.println("What is your family name?"); famName = kbReader.nextLine(); System.out.println("What is your given name?"); givName = kbReader.nextLine(); System.out.println("What is your hourly rate of pay($/h)?"); ratePay = kbReader.nextDouble(); System.out.println("How many hours you have worked this week?"); workHour= kbReader.nextInt(); System.out.println("Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.?"); charity = kbReader.nextLine().charAt(0); System.out.println("What's your tax category?(choose from A to E.)"); tax = kbReader.nextLine().charAt(0); //processing //Gross Pay double grossPay; if (workHour<=40) { grossPay=workHour*ratePay; } else { grossPay=40*ratePay+(workHour-40)*ratePay*2; } //Charity if (charity=='Y') grossPay=grossPay-20; else if(charity=='N') grossPay=grossPay-0; //Deduction double dedu; if (tax=='A') dedu=0; else if (tax=='B') dedu=grossPay*0.1; else if(tax=='C') dedu=grossPay*0.2; else if(tax=='D') dedu=grossPay*0.29; else dedu=grossPay*0.35; //net pay double netPay; netPay=grossPay-dedu; //output System.out.println("Weekly Pay Slip"); System.out.println(famName+givName); System.out.println("Gross Pay: /$"+grossPay); System.out.println("Deductions: /$"+dedu); System.out.println("Net Pay: /$"+netPay); } }
這個有啥問題呢?
What is your family name? A What is your given name? B What is your hourly rate of pay($/h)? 12 How many hours you have worked this week? 6 Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.? Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0 at java.lang.String.charAt(Unknown Source) at Arithmetic.PayCheck.main(PayCheck.java:25)
那麼很顯然了,第一個出錯的是這一行(不代表後面的沒問題)
charity = kbReader.nextLine().charAt(0);
我們在之前定義了一個
char charity;
由於java中沒有提供方法直接從鍵盤接收一個字元,但是我們可以用從鍵盤接收一個字串實現接收一個字元的功能,就是接收字串中第一個字元。
但是這個和報錯有什麼關係呢,明明思路沒問題啊。
當我們嘗試改成:
charity = kbReader.next().charAt(0);
就OK了
Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.? uu u
那麼next()和nextLine()有什麼區別呢?
next()方法在讀取內容時,會過濾掉有效字元前面的無效字元,對輸入有效字元之前遇到的空格鍵、Tab鍵或Enter鍵等結束符,next()方法會自動將其過濾掉;只有在讀取到有效字元之後,next()方法才將其後的空格鍵、Tab鍵或Enter鍵等視為結束符;所以next()方法不能得到帶空格的字串。
nextLine()方法返回的是Enter鍵之前沒有被讀取的所有字元,它是可以得到帶空格的字串的
一句話,next()方法讀取到空白符就結束,nextLine()讀取到回車結束也就是“\r”。
那麼當我們試圖用nextLine()讀取字串的第一個字元時,由於我們還沒有輸入,意味著輸入會是一個空字串,而空字串的長度是0,charAt(0)時,一定會超長。
java.lang.String.charAt() 方法返回指定索引處的char值。索引範圍是從0到length() - 1。對於陣列索引,序列的第一個char值是在索引為0,索引1,依此類推。
當我們debug看的時候了,程式碼如下:
System.out.println("Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.?");
try {
System.out.println("".charAt(0));
charity = kbReader.nextLine().charAt(0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
在這一句上加斷點:
System.out.println("".charAt(0));
如圖所示:
我們試圖列印空字串的第一個字元,由於charAt()的定義是0到length()-1,那麼此時索引超長,直接丟擲異常。
而next()就不會,因為遇到空格它就直接結束了。