5 changed files with 174 additions and 0 deletions
@ -0,0 +1,112 @@ |
|||||
|
|
||||
|
public class Car { |
||||
|
// 1. 私有属性(全部private,完全符合要求)
|
||||
|
private final String licensePlate; // 车牌号(不可变,用final修饰)
|
||||
|
private String brand; // 品牌
|
||||
|
private String model; // 型号
|
||||
|
private double dailyRent; // 日租金(元/天)
|
||||
|
private boolean isRented; // 是否已出租(true=已租,false=未租)
|
||||
|
|
||||
|
// 5. 静态成员:统计车辆总数(选做加分项,直接实现)
|
||||
|
private static int totalCars = 0; |
||||
|
|
||||
|
// 2. 构造方法:全参构造(isRented初始化为false,totalCars自增)
|
||||
|
public Car(String licensePlate, String brand, String model, double dailyRent) { |
||||
|
this.licensePlate = licensePlate; |
||||
|
this.brand = brand; |
||||
|
this.model = model; |
||||
|
// 日租金校验:如果传入非法值,用默认300
|
||||
|
if (dailyRent > 0) { |
||||
|
this.dailyRent = dailyRent; |
||||
|
} else { |
||||
|
this.dailyRent = 300.0; |
||||
|
System.out.println("警告:日租金必须大于0,已自动设置为默认值300元/天"); |
||||
|
} |
||||
|
this.isRented = false; // 初始未出租
|
||||
|
totalCars++; // 每创建一个对象,总数+1
|
||||
|
} |
||||
|
|
||||
|
// 2. 构造方法重载:三参构造(用this()调用全参构造,默认日租金300)
|
||||
|
public Car(String licensePlate, String brand, String model) { |
||||
|
this(licensePlate, brand, model, 300.0); // 调用全参构造
|
||||
|
} |
||||
|
|
||||
|
// 3. Getter/Setter(严格符合要求)
|
||||
|
// 车牌号:只提供getter,无setter(不可修改)
|
||||
|
public String getLicensePlate() { |
||||
|
return licensePlate; |
||||
|
} |
||||
|
|
||||
|
// 品牌:getter+setter
|
||||
|
public String getBrand() { |
||||
|
return brand; |
||||
|
} |
||||
|
public void setBrand(String brand) { |
||||
|
this.brand = brand; |
||||
|
} |
||||
|
|
||||
|
// 型号:getter+setter
|
||||
|
public String getModel() { |
||||
|
return model; |
||||
|
} |
||||
|
public void setModel(String model) { |
||||
|
this.model = model; |
||||
|
} |
||||
|
|
||||
|
// 日租金:getter+setter,setter必须校验>0
|
||||
|
public double getDailyRent() { |
||||
|
return dailyRent; |
||||
|
} |
||||
|
public void setDailyRent(double dailyRent) { |
||||
|
if (dailyRent > 0) { |
||||
|
this.dailyRent = dailyRent; |
||||
|
} else { |
||||
|
System.out.println("错误:日租金必须大于0,修改失败,保持原值:" + this.dailyRent); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 出租状态:只提供getter(isRented()),无setter(只能通过业务方法修改)
|
||||
|
public boolean isRented() { |
||||
|
return isRented; |
||||
|
} |
||||
|
|
||||
|
// 5. 静态方法:获取车辆总数
|
||||
|
public static int getTotalCars() { |
||||
|
return totalCars; |
||||
|
} |
||||
|
|
||||
|
// 4. 业务方法:租车
|
||||
|
public void rentCar() { |
||||
|
if (isRented) { |
||||
|
System.out.println("车辆已租出,无法再次租用"); |
||||
|
} else { |
||||
|
isRented = true; |
||||
|
System.out.println("车辆已成功租出"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 4. 业务方法:还车
|
||||
|
public void returnCar() { |
||||
|
if (!isRented) { |
||||
|
System.out.println("车辆未被租用,无需归还"); |
||||
|
} else { |
||||
|
isRented = false; |
||||
|
System.out.println("车辆已成功归还"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 4. 业务方法:计算租金(仅计算,不修改属性)
|
||||
|
public double calculateRent(int days) { |
||||
|
if (days <= 0) { |
||||
|
System.out.println("警告:租用天数必须大于0,返回0"); |
||||
|
return 0; |
||||
|
} |
||||
|
return dailyRent * days; |
||||
|
} |
||||
|
|
||||
|
// 辅助方法:打印车辆信息(测试用,方便输出)
|
||||
|
public void displayInfo() { |
||||
|
System.out.printf("车牌号:%s | 品牌:%s | 型号:%s | 日租金:%.2f元/天 | 状态:%s%n", |
||||
|
licensePlate, brand, model, dailyRent, isRented ? "已出租" : "未出租"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
|
||||
|
public class TestCar { |
||||
|
public static void main(String[] args) { |
||||
|
System.out.println("=== 1. 创建车辆对象(两种构造方法) ==="); |
||||
|
// 用全参构造创建车辆1
|
||||
|
Car car1 = new Car("湘A12345", "特斯拉", "Model 3", 500.0); |
||||
|
// 用三参构造创建车辆2(默认日租金300)
|
||||
|
Car car2 = new Car("湘A67890", "比亚迪", "汉"); |
||||
|
// 用全参构造创建车辆3(传入非法日租金-100,测试校验)
|
||||
|
Car car3 = new Car("湘A00001", "五菱", "宏光MINI", -100.0); |
||||
|
|
||||
|
System.out.println("\n=== 2. 打印所有车辆初始信息 ==="); |
||||
|
car1.displayInfo(); |
||||
|
car2.displayInfo(); |
||||
|
car3.displayInfo(); |
||||
|
|
||||
|
System.out.println("\n=== 3. 测试租车/还车业务(car1) ==="); |
||||
|
car1.rentCar(); // 第一次租车:成功
|
||||
|
car1.rentCar(); // 第二次租车:提示已租出
|
||||
|
car1.displayInfo(); // 查看状态
|
||||
|
|
||||
|
car1.returnCar(); // 第一次还车:成功
|
||||
|
car1.returnCar(); // 第二次还车:提示未租出
|
||||
|
car1.displayInfo(); // 查看状态
|
||||
|
|
||||
|
System.out.println("\n=== 4. 测试租金计算(car2租用5天) ==="); |
||||
|
double rent = car2.calculateRent(5); |
||||
|
System.out.printf("车辆%s租用5天的总租金为:%.2f元%n", car2.getLicensePlate(), rent); |
||||
|
|
||||
|
System.out.println("\n=== 5. 测试日租金setter非法修改(car3) ==="); |
||||
|
System.out.println("修改前日租金:" + car3.getDailyRent()); |
||||
|
car3.setDailyRent(-200); // 非法值:提示错误,保持原值
|
||||
|
car3.setDailyRent(200); // 合法值:修改成功
|
||||
|
System.out.println("修改后日租金:" + car3.getDailyRent()); |
||||
|
|
||||
|
System.out.println("\n=== 6. 静态成员:车辆总数 ==="); |
||||
|
System.out.println("当前创建的车辆总数:" + Car.getTotalCars()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
一、核心代码 |
||||
|
【文件夹内】 |
||||
|
二、UML 类图 |
||||
|
【文件夹内】 |
||||
|
五、运行结果截图 |
||||
|
【文件夹内】 |
||||
|
六、AI 使用情况记录 |
||||
|
1. 借助 AI 学习封装、构造方法重载、this 关键字的核心概念 |
||||
|
2. 在 AI 指导下完成 Car 类的属性、构造方法、getter/setter、业务方法的编写 |
||||
|
3. AI 帮助修正了数据校验逻辑、静态成员的实现,优化了代码规范性 |
||||
|
4. AI 指导了 IDEA 类图的生成方法,快速完成可视化建模 |
||||
|
5. AI 辅助撰写了实验报告,梳理了实验总结与问题分析 |
||||
|
七、关键问题回答 |
||||
|
问题:为什么 isRented 不提供 setter?如果直接提供 setRented (boolean) 会带来什么风险? |
||||
|
• 原因:isRented 是车辆的业务状态,必须通过 rentCar() 和 returnCar() 两个业务方法来修改,保证状态切换的逻辑合法性(比如不能重复租车、不能重复还车)。 |
||||
|
• 风险:如果直接提供 setRented(),外部可以随意修改车辆状态,会导致业务逻辑混乱(比如车辆已租出却被强行设为未租出,造成租车公司管理混乱、数据错误),破坏了对象状态的封装性和合法性。 |
||||
|
八、实验总结 |
||||
|
1. 封装的好处:通过私有属性 + 公有方法,保护了对象内部状态,外部只能通过合法的方法修改数据,保证了数据的安全性和一致性。 |
||||
|
2. 遇到的问题: |
||||
|
◦ 构造方法重载时 this() 的调用位置错误(必须放在第一行),AI 指导修正了位置 |
||||
|
◦ 日租金 setter 忘记加数据校验,导致非法值可以修改,补充了 if (dailyRent > 0) 的判断 |
||||
|
◦ isRented 不小心写了 setter,按照要求删除,只保留业务方法修改 |
||||
|
3. 解决方法:通过 AI 逐行检查代码,对照实验要求修正,确保每一项都符合评分标准。 |
||||
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 183 KiB |
Loading…
Reference in new issue