在 Java 中,程式的檔案組織遵循一個簡單的規則:只要檔案屬於同一個 package(或未指定 package 的情況下,屬於預設 package),類別之間就可以互相存取。 ## 設計Date (日期)類別及測試 --- Date私有成員變數有3: int day; // 1 to 31 int month; // 1 to 12 int year; // 2014 等西元年 Date 之靜態類別欄位有 1: final static int[ ] daysPerMonth = { 0, 31,28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //代表非閏年時的每月天數 ```java public class Date { private int day; private int month; private int year; private final static int[] daysPerMonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ``` ### a. 此類別建構函式如下:Date( int m, int d, int y):將 year 設為y。 如果m 在1 至12 間,則將month 設為m;否則將month 設為1。 如果month 那個月份含有d 那天,則將day 設為d; 否則將day設為1。 [註:須檢查 year是否為閏年(leap year),如果是閏年,則 month 及day 可以為2 及29 (代表2 月29 日);如果 year 不是閏年,則當month = 2 且d >= 29時,應將 day 設為1 (代表2 月1 日)。] ```java public Date(int m, int d, int y) { this.year = y; if (m >= 1 && m <= 12) { this.month = m; } else { this.month = 1; } if (month == 2 && d == 29 && checkLeap(year)) { this.day = 29; } else if (d >= 1 && d <= daysPerMonth[month]) { this.day = d; } else { //當day超過month的天數時,將day設為1 this.day = 1; } } ``` ### b. i. 靜態方法:檢查是否為閏年,是傳回true,否傳回false [閏年規則](https://flywithjuan.com/normal-year-leap-year/) ```java public static boolean checkLeap(int y) { return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); } ``` ii. 實例方法:檢查物件是否處於閏年,是傳回true,否傳回false ```java public boolean isLeap() { return checkLeap(this.year); } ``` iii. 格式化日期為字串,將日期格式化為 mm/dd/yyyy 的字串 ```java @Override public String toString() { return String.format("%02d/%02d/%04d", month, day, year); } ``` iv.計算該日期是當年的第幾天 ```java public int yearDate() { int totalDays = day; for (int i = 1; i < month; i++) { totalDays += daysPerMonth[i]; } if (month > 2 && checkLeap(year)) { totalDays++; } return totalDays; } } ``` ### c. 主程式main ```java public class TestDate { public static void main(String[] args){ Date d1 = new Date(7,29,2004); System.out.println("d1: " + d1); Date d2 = new Date( 12, 31, 2023); System.out.println("d2: " + d2); Date d3 = new Date( 2, 29, 2024); System.out.println("d3: " + d3); Date d4 = new Date( 2, 29, 2025); System.out.println("d4: " + d4); System.out.println("-------------------------"); System.out.println("d1 是其所在年份的第 " + d1.yearDate() + " 天"); System.out.println("d2 是其所在年份的第 " + d2.yearDate() + " 天"); System.out.println("d3 是其所在年份的第 " + d3.yearDate() + " 天"); System.out.println("d4 是其所在年份的第 " + d4.yearDate() + " 天"); } } ``` --- ## Circle Point物件代表二維平面上的一個點,Point 類別之成員變數有2: 1. int x:代表該點的x 軸位置。 1. int y:代表該點的y 軸位置。 Point 類別方法如下: 1. 建構子Point( int x1, int y1):初始化x、y 這兩個成員變數為x1 及y1; 1. 建構子Point( ):將x、y 這兩個成員變數初始化為0, 0; [本題要求必須使用this ] 1. void setPoint(int setX, int setY):重新設定x、y 這兩個成員變數; ```java public class Point { int x; int y; public Point(int x1, int y1){ this.x = x1; this.y = y1; } public Point(){ this.x = 0; this.y = 0; } public void setPoint(int setX, int setY){ this.x = setX; this.y = setY; } public int getX(){ return x; } public int getY(){ return y; } } ``` 本題要求設計的Circle(圓形)類別,其成員變數中,繼承自Point 類別的 x, y 表示此圓形物件的圓心的座標,有如下1新增成員變數: 1. double radius:代表半徑。 Circle類別方法如下: 3. 建構子Circle(int x, int y, double length):必須使用super( )方法達成成員變數x、y的初始化,並初始化成員變數radius 為length。 4. double getArea( )方法,此方法會回傳此Circle 物件的面積,計算方式為π* radius * radius。 5. String toString( )方法:會回傳如“Center: (5, 5) ; Radius = 5.00;” 格式之字串,表示該圓形物件之圓心座標x、y 及半徑值。 ```java class Circle extends Point { double radius; public Circle(int x, int y, double length){ super(x, y); this.radius = length; } public double getArea(){ return Math.PI * radius * radius; } public String toString(){ return String.format("Center: (%d, %d); Radius = %.2f;", getX(), getY(), radius); } } ``` main ```java public class TestCircle { public static void main(String[] args){ Circle circle = new Circle(5, 5,5); System.out.println(circle.toString()); System.out.printf("Area = %.2f%n", circle.getArea()); } } ``` --- ## 12.1 (NumberFormatException) 程式 7.9,Calculator.java,是一個簡單的命令列 計算器。請注意,如果任何操作數為非數字,則程式將終止。寫一個有處理非數字運算元的異常處理程序的程式;然後編寫另一個程式而不使用異常處理程序來 實現相同的目標。你的程式應該在退出之前顯示一則訊息,通知使用者錯誤的 操作數類型。 ### 使用有處理非數字運算元的異常處理程序的程式 ```java /** Main method */ public class Calculator_use_Exception { public static void main(String[] args) { if (args.length != 3) { System.out.println( "Usage: java Calculator operand1 operator operand2"); System.exit(0); } try { // 嘗試將運算元轉換為整數(可能會拋出 NumberFormatException) int operand1 = Integer.parseInt(args[0]); int operand2 = Integer.parseInt(args[2]); char operator = args[1].charAt(0); int result = calculate(operand1, operator, operand2); System.out.println(args[0] + " " + args[1] + " " + args[2] + " = " + result); } catch (NumberFormatException ex) {// 捕捉非數字運算元 System.out.println("Error Input: " + ex.getMessage()); } catch (ArithmeticException ex) {// 捕捉算術運算錯誤(如除以零) System.out.println("Error: " + ex.getMessage()); } } private static int calculate(int operand1, char operator, int operand2) { switch (operator) { case '+': return operand1 + operand2; case '-': return operand1 - operand2; case '*': return operand1 * operand2; case '/': if (operand2 == 0) {// 檢查是否分母為零 throw new ArithmeticException("Division by zero."); } return operand1 / operand2; default:// 如果運算符無效,拋出例外 throw new IllegalArgumentException("Invalid operator: " + operator); } } } ``` ``` (base) rain@MacBook-Air ~ % java Calculator_use_Exception 2 / 0 Error: Division by zero. ``` ``` (base) rain@MacBook-Air ~ % java Calculator_use_Exception 2 / 2x Error Input: For input string: "2x" ``` ``` (base) rain@MacBook-Air ~ % java Calculator_use_Exception -2 / 2 -2 / 2 = -1 ``` ### 不使用異常處理程序 ```java public class Calculator_no_use_Exception { public static boolean isInt(String num) { // 判斷字串是否非空且符合整數格式(允許負號) return num != null && num.matches("-?\\d+"); } public static void main(String[] args) { // 檢查是否提供了 3 個命令列參數 if (args.length != 3) { System.out.println( "Usage: java Calculator operand1 operator operand2"); System.exit(0); } // 運算結果變數 int result = 0; // 檢查第一個運算元是否為整數 if (!isInt(args[0])) { System.out.printf("Wrong Input: %s\n", args[0]); return; // 提前結束程式 } // 檢查第二個運算元是否為整數 if (!isInt(args[2])) { System.out.printf("Wrong Input: %s\n", args[2]); return; // 提前結束程式 } switch (args[1].charAt(0)) { case '+': result = Integer.parseInt(args[0]) + Integer.parseInt(args[2]); break; case '-': result = Integer.parseInt(args[0]) - Integer.parseInt(args[2]); break; case '*': result = Integer.parseInt(args[0]) * Integer.parseInt(args[2]); break; case '/': if (Integer.parseInt(args[2]) == 0) { System.out.println("Error: Division by zero."); return; } result = Integer.parseInt(args[0]) / Integer.parseInt(args[2]); break; default: // 如果運算符無效 System.out.printf("Invalid explanation: %s\n", args[1]); return; } // 顯示運算結果 System.out.println(args[0] + " " + args[1] + " " + args[2] + " = " + result); } } ``` ``` (base) rain@MacBook-Air ~ % java Calculator_no_use_Exception 2 / 0 Error: Division by zero. ``` ``` (base) rain@MacBook-Air ~ % java Calculator_no_use_Exception 2 / 2x Wrong Input: 2x ``` ``` (base) rain@MacBook-Air ~ % java Calculator_no_use_Exception -2 / 2 -2 / 2 = -1 ``` --- ## 12.2 使用以下兩個陣列,撰寫一個程式,提示使用者輸入一個 1 到 12 之間的整數,並根據輸入的數字顯示對應的月份及其天數。若使用者輸入的數字不在範圍內,程式應透過捕捉 ArrayIndexOutOfBoundsException 例外來顯示「wrong number」。 ```javascript import java.util.Scanner; public class homework12_2 { public static void main(String[] args) { String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; int[] dom = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; Scanner scanner = new Scanner(System.in); System.out.print("請輸入1-12其中一個數字: "); try { int monthIndex = scanner.nextInt() - 1; System.out.println(months[monthIndex] + " 有 " + dom[monthIndex] + " 天"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("輸入的數字不在範圍內"); } } } ```