slug
type
status
category
date
summary
tags
password
icon
3.9.1
下面把这段
Person 代码从上到下讲清楚,并指出运行结果与可改进点。类与成员(字段)
- 三个实例变量(字段),访问修饰符是
private,对外隐藏,体现封装。
- 类型都是
String。在 Java 中,对象类型的字段若未显式赋值,默认值为null。因此除非在构造器或 setter 里设置,否则email、phoneNumber都是null。
构造器(Constructor)
- 仅接收
name,用this.name = name;把形参赋给当前对象的字段。
this用来消歧:左边是字段,右边是参数。
- 因为只有这个单参构造器,所以创建对象时必须提供名字;但
email和phoneNumber仍保持默认的null。
访问器/修改器(Getters/Setters)
- 标准 JavaBean 风格:对外提供受控访问与修改。
- 目前没有任何校验逻辑(比如邮箱格式、手机号格式),所以可以被设为任意字符串甚至
null。
重写 toString
- 当对象被打印或拼接为字符串时调用。
- 这里直接把三个字段用空格连接。如果某个字段是
null,字符串中就会出现字面量"null"。这不是异常,只是展示出来的文本。
小建议:在方法前加 @Override 注解,编译期能帮忙校验确实重写了父类方法。
main 测试流程与输出
p1:只传入 name,email与phoneNumber都是默认null。
打印时调用
toString(),输出:p2:先用 name 构造,再通过 setters 设定email和phoneNumber。
打印输出:
(打印顺序就是上面两行,第一行是
p1,第二行是 p2。)代码要点小结
- 封装:字段私有 + getters/setters 公有。
- 对象默认值:未初始化的
String字段为null。
this的作用:区分字段与同名参数。
toString()的行为:直接串接,null会以文本"null"显示。
3.9.2
下面把这段代码按“结构—运行过程—关键点—改进建议”四层拆开讲清楚。
1) 程序结构与职责
class Pay- 字段:
private double pay;保存当前薪资。 - 构造器:
public Pay(double p)用传入的p初始化pay。 - 访问器:
getPay()返回当前pay值。 - 行为:
calculatePayWithOvertime()计算加班后的薪资:它把当前对象this传给Overtime的构造器,由对方根据规则算出新的薪资,再把结果回写到自身的pay字段里(产生就地修改/副作用)。
class Overtime(包可见的辅助类)- 字段:
private double payWithOvertime;保存“含加班”的薪资。 - 构造器:
public Overtime(Pay p)从传入的Pay对象读取p.getPay(),按 1.5 倍加成计算并保存。 - 访问器:
getOvertimePay()返回计算结果。
关系:Pay **组合(composition)**了一个 Overtime 计算器来完成加班逻辑;不是继承而是“把工作交给帮手类”。
2) 运行过程(逐行跟踪)
main 方法:Pay myPay = new Pay(100.0);- 创建一个
Pay对象,内部pay = 100.0。
myPay.calculatePayWithOvertime();- 进入方法内部:
- 这里的
this就是myPay本身。 - 进入
Overtime构造器:读取p.getPay()得到100.0,乘以1.5,将payWithOvertime = 150.0。 - 把
150.0写回myPay的私有字段pay。
a)
Overtime ot = new Overtime(this);b)
pay = ot.getOvertimePay();System.out.println(myPay.getPay());- 打印
150.0。
程序输出:
150.03) 关键知识点
this的用法:在Pay.calculatePayWithOvertime()中,this指向当前Pay实例。将其传给Overtime构造器,使对方可以通过公开接口getPay()读取当前薪资。
- 封装(encapsulation):
pay与payWithOvertime都是private,外部只能通过 getter 读,不能直接改数据(Pay自己在方法里当然能改自己的字段)。
- 对象引用传递:Java 形参按值传递,但值是对象引用。
Overtime(Pay p)得到的是指向Pay对象的引用副本,因此能调用p.getPay()。
- 副作用/可变状态:
calculatePayWithOvertime()会修改Pay对象内部状态(把pay从 100 改成 150)。这在业务上合理,但在某些设计场景可能希望无副作用。
- 可见性:
Overtime没有显式public,因此是包可见,只能在同一包内被访问,适合作为内部的“领域服务/计算器”。
3.9.4
下面把这段
BankAccount 代码按结构、语义与运行过程逐层拆解说明,并给出程序运行时的“逐步账本”。代码结构与面向对象要点
- 类与封装:
BankAccount有 3 个私有实例变量:name(户名)、accountNumber(账号)、balance(余额)。私有化保证只能通过公开方法改动余额,体现封装。
- 构造方法重载 + 构造链
BankAccount(String name, String accountNumber, double balance):三参构造,完整初始化。BankAccount(String name, String accountNumber):二参构造,调用上面的三参构造(this(name, accountNumber, 0.0);),把初始余额设为 0。this(...)必须放在构造器第一行。
- 存取逻辑
deposit(double amount):只接受 正数 存款;成功则balance += amount并打印“xx deposited $amount”。否则提示“Deposit amount must be positive.”withdraw(double amount):取款需满足 正数 且 不超过余额;成功则balance -= amount并打印“xx withdrew $amount”。若超额,提示“Insufficient funds for xx”;若非正数,提示“Withdrawal amount must be positive.”
toString()重写:返回三行字符串,展示户名、账号和余额。System.out.println(acc1);会隐式调用acc1.toString()。
this的用法:在构造器和方法中用this.xxx明确访问当前对象的字段,保证不与形参同名变量混淆。
main 执行流程与输出
阶段 1:初始账户打印
acc1:余额 500.0
acc2:余额 0.0
阶段 2:交易测试
阶段 3:期末账户打印
acc1:余额 600.0
acc2:余额 300.0
预期控制台输出(顺序与换行基本如下)
小而重要的细节
- 自动类型提升与打印:
deposit(200)传入的是int字面量,但方法形参是double,因此输出为200.0(double的默认字符串格式)。
- 浮点钱款的精度:示例教学用
double简洁直观;在真实金融系统中应使用BigDecimal(或“分”为单位的整数)避免二进制浮点误差。
- 改进建议(可选)
- 增加
getBalance()/getName()等访问器;必要时让accountNumber设为不可变(final),并校验账号格式。 toString()可用String.format("...$%.2f", balance)固定两位小数。- 对存取款返回
boolean表示是否成功,而不仅是打印提示,便于上层逻辑处理。
如果你想,我可以把它改造成返回布尔值 + 使用
BigDecimal + 两位小数格式的版本,或者加上转账方法与简单单元测试示例。- 作者:现代数学启蒙
- 链接:https://www.math1234567.com/article/codeexplained39
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章












