在 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("輸入的數字不在範圍內");
}
}
}
```