软件构造复习中关于不变性的一个疑问以及代码验证

  在查看MIT的软件构造讲义时,我发现有一个练习如下:

    /** Represents an immutable right triangle. */
      class RightTriangle {
/*A*/     private double[] sides;

/*B*/     public final int hypotenuse = 2;

          /** Make a right triangle.
           * @param legA, legB  the two legs of the triangle
           * @param hypotenuse    the hypotenuse of the triangle.
 *C*       *        Requires hypotenuse^2 = legA^2 + legB^2 
           *           (within the error tolerance of double arithmetic)
           */
          public RightTriangle(double legA, double legB, double hypotenuse) {
/*D*/         this.sides = new double[] { legA, legB };
/*D*/         this.hypotenuse = hypotenuse;
          }

          /** Get the two sides of the right triangle.
           *  @return two-element array with the triangle's side lengths
           */
          public double[] getAllSides() {
/*E*/         return sides;
          }

          /** @param factor to multiply the sides by
           *  @return a triangle made from this triangle by 
           *  multiplying all side lengths by factor.
           */
          public RightTriangle scale(double factor) {
              return new RightTriangle(sides[0]*factor, sides[1]*factor, hypotenuse*factor);
          }

          /** @return a regular triangle made from this triangle.
           *  A regular right triangle is one in which
           *  both legs have the same length.
           */
          public RightTriangle regularize() {
              double bigLeg = Math.max(side[0], side[1]);
              return new RightTriangle (bigLeg, bigLeg, hypotenuse);
          }

      }

  这里说E处是有问题的代码,即

public double[] getAllSides() {
/*E*/         return sides;
          }

  乍一看这里返回了一个原来的引用,可能导致表示泄露。但是又一想,double是不可变类型啊!这里即使改变了原来的double,但是return出去的double也不是原来那个double了,为什么会说代码有问题呢?

  为了证实我的判断,我写了下面的一段代码:

package hetest;

public class fianltest {
    private int ints;
    public int returnints()
    {
        return this.ints;
    }
    public fianltest (int ints) {
        this.ints=ints;
    }
    public static void main(String args[])
    {
        fianltest f=new fianltest(2);
        int g=f.returnints();
        g=g+1;
        System.out.println(f.returnints());
                
    }
}

  这段代码运行结果是2,即没有改变原来的int,那说明double确实也是不可变的,问题出在哪呢?

  这时我突然想起来,这里实际上返回的是double数组,那double数组是不是可变的呢?我打算自己验证一下。于是有了下面的代码:

package hetest;

public class fianltest {
    private int [] ints;
    public int[] returnints()
    {
        return this.ints;
    }
    public fianltest (int[] ints) {
        this.ints=ints;
    }
    public static void main(String args[])
    {
        int [] i=new int[] {2};
        fianltest f=new fianltest(i);
        int[] g=f.returnints();
        g[0]=3;
        System.out.println(f.returnints()[0]);
        System.out.println(g[0]);        
    }
}

  这段代码的运行结果是3,3.这也说明了,这里对数组别名的更改影响到了内部表示,也就是说double数组是可变的!

  

原文地址:https://www.cnblogs.com/upuphe/p/13258640.html