Effective Java - 必要时进行保护性拷贝

2022-07-23  本文已影响0人  DZQANN

第50条 必要时进行保护性拷贝

  1. Example:

    public final class Period {
        private final Date start;
        private final Date end;
    
        public Period(Date start, Date end) {
            if (start.compareTo(end) > 0)
                throw new IllegalArgumentException(
                        start + " after " + end);
            this.start = start;
            this.end   = end;
        }
    
        public Date start() {
            return start;
        }
        public Date end() {
            return end;
        }
    }
    

    这里有一个比较严重的问题,是虽然把startend变成了final,但是Date本身还是一个可变的,如果外边塞了start之后又改变了Date的值,就会导致Period的计算结果错误。

    可以修改为:

    public Period(Date start, Date end) {
      if (start.compareTo(end) > 0)
          throw new IllegalArgumentException(
          start + " after " + end);
      this.start = new Date(start.getTime());
      this.end   = new Date(end.getTime());
    }
    
  2. Date已经过时了,不应该在新代码中依然使用Date

  3. 对于构造器里面的每个可变参数进行保护性拷贝是必要的

  4. 保护性拷贝实在检查参数的有效性之前进行的,并且有效性检查针对的是拷贝之后的对象。这么做的目的是避免多线程对于变量的修改

思考

  1. 这一节说的问题确实是存在的,不过在项目里不需要太注意。类里面的成员应该尽可能保证只读
  2. 如果编写了大部分人都会调用的底层接口,则需要考虑对入参进行复制。特别是类成员的get方法,在这种情况下应该尽量返回一个副本。底层接口不会知道使用比人是怎么用它的,只能自己尽量保证安全
上一篇 下一篇

猜你喜欢

热点阅读