设计一个不可变类
1 实例说明:写一个不可改变类
1.1 一些类
// car location
public class Location{
private double x;
private double y;
public Location(double x, double y){
this.x = x;
this.y = y;
}
public double getX() {return x;}
public double getY() {return y;}
public void setXY(double x, double y){
this.x = x;
this.y = y;
}
}
public class CarLoactionTracker{
private Map<String, Location> loactionMap = new CurrentHashMap<>();
// @Param carCode 车辆编码
// @Param x 位置信息
// @Param y 位置信息
public void updateLocation(String carCode, double x, double y){
Location location = locationMap.get(carCode);
location.setXY(x, y)
}
public Location getLocation(String carCode) {return locationMap.get(carCode);}
}
- 当线程A调用updateLocation()方法,线程B调用getLocation()方法时,就可能产生并发问题
- A刚刚更新了X,还没来得及更新Y
- B读取了location,结果汽车到了从未到达过的坐标
因此必须要保证,location是不能被修改的,当要更新位置时,就应该新建一个location对象,而不是修改已有的对象。
也就是说,要把Location类变为不可改变的类。
把一个类变成不可改变的类的思路如下:
- 用final修饰所有成员变量,避免被修改。
- 用private修饰所有成员变量,防止子类及其他地方通过引用来修改变量的值。
- 禁止提供修改内部状态的结构(例如:set方法)
- 用final修饰类,让类不可被继承。
- 针对数组和集合,提供给外部之前,要做防御性复制。具体说明如下所示。
public final class DefensiveReplicaDemo {
// create a final list
public final List<Integer> data = new ArrayList<>();
// define a construct method
// add "1", "2" into the list
public DefensiveReplicaDemo {
data.add(1);
data.add(2);
}
// define a method to return the list
public List<Integer> getData(){
return data;
}
public static void main(String[] args){
// demo: 1, 2
DefensiveReplicaDemo demo = new DefensiveReplicaDemo();
// reference to demo by getData
List<Integer> data = demo.getData();
data.add(3);
// now in demo: 1, 2, 3
// demo is unsafe due to the reference
}
}
// modify the getData methond
public List<Integer> getData(){
return Collections.unmodifiableList(new ArrayList<>(Data));
}