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


      在查看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数组是可变的!

      

  • 相关阅读:
    写了个限制文本框输入最大长度的jquery插件
    A2D JS框架
    在.Net中执行js
    C# Socket的粘包处理
    分布式EventBus的Socket实现
    读写分离子系统
    缓存子系统如何设计(Cachable tag, Memcache/redis support, xml config support, LRU/LFU/本地缓存命中率)
    pip install在Windows下报错解决
    Centos 6.9安装配置MongoDB
    Centos6.9安装Node.js+npm爬坑
  • 原文地址:https://www.cnblogs.com/upuphe/p/13258640.html
Copyright © 2020-2023  润新知