设计一个不可变类

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类变为不可改变的类。

把一个类变成不可改变的类的思路如下:

  1. 用final修饰所有成员变量,避免被修改。
  2. 用private修饰所有成员变量,防止子类及其他地方通过引用来修改变量的值。
  3. 禁止提供修改内部状态的结构(例如:set方法)
  4. 用final修饰类,让类不可被继承。
  5. 针对数组和集合,提供给外部之前,要做防御性复制。具体说明如下所示。
    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));
    }

posted @ 2021-06-09 10:29  Yiyang_Cai  阅读(73)  评论(0编辑  收藏  举报