slug
type
status
category
date
summary
tags
password
icon

3.9.1

 

下面把这段 Person 代码从上到下讲清楚,并指出运行结果与可改进点。

类与成员(字段)

  • 三个实例变量(字段),访问修饰符是 private,对外隐藏,体现封装
  • 类型都是 String。在 Java 中,对象类型的字段若未显式赋值,默认值为 null。因此除非在构造器或 setter 里设置,否则 emailphoneNumber 都是 null

构造器(Constructor)

  • 仅接收 name,用 this.name = name;形参赋给当前对象的字段
  • this 用来消歧:左边是字段,右边是参数。
  • 因为只有这个单参构造器,所以创建对象时必须提供名字;但 emailphoneNumber 仍保持默认的 null

访问器/修改器(Getters/Setters)

  • 标准 JavaBean 风格:对外提供受控访问与修改。
  • 目前没有任何校验逻辑(比如邮箱格式、手机号格式),所以可以被设为任意字符串甚至 null

重写 toString

  • 当对象被打印或拼接为字符串时调用。
  • 这里直接把三个字段用空格连接。如果某个字段是 null,字符串中就会出现字面量 "null"。这不是异常,只是展示出来的文本。
小建议:在方法前加 @Override 注解,编译期能帮忙校验确实重写了父类方法。

main 测试流程与输出

  • p1:只传入 name,emailphoneNumber 都是默认 null
    • 打印时调用 toString(),输出:
  • p2:先用 name 构造,再通过 setters 设定 emailphoneNumber
    • 打印输出:
(打印顺序就是上面两行,第一行是 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 方法:
  1. Pay myPay = new Pay(100.0);
      • 创建一个 Pay 对象,内部 pay = 100.0
  1. myPay.calculatePayWithOvertime();
      • 进入方法内部:
        • a) Overtime ot = new Overtime(this);
        • 这里的 this 就是 myPay 本身。
        • 进入 Overtime 构造器:读取 p.getPay() 得到 100.0,乘以 1.5,将 payWithOvertime = 150.0
          • b) pay = ot.getOvertimePay();
        • 150.0 写回 myPay 的私有字段 pay
  1. System.out.println(myPay.getPay());
      • 打印 150.0
程序输出:150.0

3) 关键知识点

  • this 的用法:在 Pay.calculatePayWithOvertime() 中,this 指向当前 Pay 实例。将其传给 Overtime 构造器,使对方可以通过公开接口 getPay() 读取当前薪资。
  • 封装(encapsulation)
    • paypayWithOvertime 都是 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.0double 的默认字符串格式)。
  • 浮点钱款的精度:示例教学用 double 简洁直观;在真实金融系统中应使用 BigDecimal(或“分”为单位的整数)避免二进制浮点误差。
  • 改进建议(可选)
    • 增加 getBalance() / getName() 等访问器;必要时让 accountNumber 设为不可变(final),并校验账号格式。
    • toString() 可用 String.format("...$%.2f", balance) 固定两位小数。
    • 对存取款返回 boolean 表示是否成功,而不仅是打印提示,便于上层逻辑处理。
如果你想,我可以把它改造成返回布尔值 + 使用 BigDecimal + 两位小数格式的版本,或者加上转账方法与简单单元测试示例。
 

 
 
 
 
CSAWESOME 4.6代码详解CSAWESOME3.8 代码详解
Loading...