AP CSA 3.6|BlueJ 小练习:谁改了 Alex 的地址?
Who Changed My Address? Alex 的地址明明是在创建对象时复制的,为什么后来还是会被别人修改?用 BlueJ 的 Object Bench 亲自找出原因。
0 · 准备两个 Class(3 min)
在 BlueJ 新建项目 ReferenceLab,分别创建 Address 和 Person,复制代码后 Compile。
Address.java
public class Address
{
private String city;
public Address(String c)
{
city = c;
}
// Copy constructor
public Address(Address other)
{
city = other.getCity();
}
public String getCity()
{
return city;
}
public void setCity(String c)
{
city = c;
}
}
Person.java
public class Person
{
private String name;
private Address addr;
public Person(String n, Address a)
{
name = n;
addr = new Address(a);
}
public String getCity()
{
return addr.getCity();
}
public Address getAddress()
{
return addr;
}
}
观察重点:每出现一次 new,就画一个新 object;每出现一次 reference 赋值或返回,就画一条箭头。
1 · Experiment A:改变 home(4 min)
- 在 Object Bench 创建
new Address("Chengdu"),命名为home。 - 创建
new Person("Alex", home),命名为alex。 - 先预测:修改
home后,Alex 会住在哪里? - 右键
home→setCity("Shanghai");再右键alex→getCity()。
Predict: alex.getCity() → Chengdu / Shanghai ?
查看结果与 Reference 图
Chengdu. Person constructor 中的 new Address(a) 创建了独立的地址对象(defensive copy)。
home ──► Address #1: Shanghai
alex.addr ──► Address #2: Chengdu
2 · Experiment B:改变 returned(4 min)
- 右键
alex→getAddress()。 - 在返回对象的窗口中点击 Get,把它放到 Object Bench,命名为
returned。 - 先预测:改变
returned会影响 Alex 吗? - 右键
returned→setCity("Beijing");再调用alex.getCity()。
Predict: alex.getCity() → Chengdu / Beijing ?
查看结果与 Reference 图
Beijing! getAddress() 直接 return addr;,所以 returned 与 alex.addr 指向同一个对象(aliasing)。
alex.addr ──┐
├──► Address #2: Beijing
returned ───┘
即使 addr 是 private,返回其 reference 仍可能允许外部代码修改内部对象。
3 · Fix it:只改一行(3 min)
任务:只修改 Person.getAddress() 中的一行,让返回的地址成为独立 object。
public Address getAddress()
{
return ____________;
}
改完后 Compile,重新创建 home、alex 和 returned,再重复 Experiment B。旧 Object Bench 中的对象不要继续使用。
查看修复代码
public Address getAddress()
{
return new Address(addr);
}
现在修改 returned 不会影响 alex,因为 getter 返回了新的 Address object。
4 · Exit Ticket(1 min)
不用运行代码,直接预测:
Address a = new Address("Chengdu");
Address b = a;
Address c = new Address(a);
b.setCity("Tokyo");
Questions: ① 创建了几个 Address objects?② a、b、c 各自的城市是什么?
查看答案
2 个 objects。 a 和 b 都是 Tokyo;c 仍然是 Chengdu。