不可变数据类型和可变数据类型(mutable &immutable)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sup_chao/article/details/84848237
一、基本概念

以下所有的内容都是基于内存地址来说的。
不可变数据类型: 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。
可变数据类型 :当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。
总结:不可变数据类型更改后地址发生改变,可变数据类型更改地址不发生改变

二、从Java的String&StringBuilder中看差别

这里引入Snapshot diagrams,不清楚的可以点击Snapshot diagrams跳转到下面查看。
String:不可变数据类型
StringBuilder:可变数据类型

  1. 更改对象的值
    不可变数据类型是在重新将引用指向一个新地址,新地址中为更改后的值。 可变数据类型则在原来的地址上直接更改对象值。

    String s = "a";  s = 'ab';
    StringBuilder sb = "a";   sb = "ab";
    

    string类型更改值  StringBuilder类型更改值

  2. 一个地址被多个对象引用时

    String s = "a";  s = 'ab';
    StringBuilder sb = "a";   sb = "ab";
    
    String t = s;
    t = t + "c";
    StringBuilder tb = sb;
    tb.append("c");
    

    在这里插入图片描述

  3. 其他差别
    不可变数据类型:对其修改会产生大量的临时拷贝(需要垃圾回收)
    可变数据类型:最少化拷贝以提高效率,可以共享数据

三、可变数据使用风险
  1. 传参传递可变数据类型
    //计算List所有数据绝对值之和
    //风险:更改了list中的值
    public static int sumAbsolute(List<Integer> list) {
        for(int i = 0; i < list.size(); i++) 
          list.set(i,Math.abs(list.get(i)));
        return sum(list);
     }
    
  2. 返回可变数据类型
    //生成聚会时间
    //风险:在更改partyDate时同样会更改answer的值
      private static Date answer = null;
      public static Date startOfString() {
        if(answer == null)
          answer = newDate();
        return answer;
      }
      public static void partyPlanning() {
        Date partyDate =  startOfString();
        partyDate.setMonth(partyDate.getMonth()+1);
      }
    
四、保障可变数据类型数据的安全

通过防御式拷贝,给客户端返回一个全新的Date对象,例如上图中第二个例子。

return new Date(groundhogAnswer.getTime());
五、(补充)Snapshot diagrams

Snapshot diagrams
用于描述程序运行时内部状态的快照图。 其作用:
(1)便于程序员之间的交流
(2)便于刻画各类变量随时间变化的过程
(3)便于解释设计思路

  1. 基本数据类型
    在这里插入图片描述
  2. 对象类型
    在这里插入图片描述
  3. 不可变类型的对象
    不可变对象:用双线椭圆
    可变对象:用单线椭圆
    在这里插入图片描述在这里插入图片描述
  4. 不可变的引用
    即带final关键字的引用,用双线箭头
    在这里插入图片描述
  5. 其他
    不可变引用指向可变引用
    final StringBuilder sb = new StringBuilder("abc");
    sb.append("d"); //引用是不可变的,但指向的值却可以是可变的 
    sb = new StringBuilder("e"); //编译阶段出错:The final variable sb cannot be assigned
    System.out.println(sb);
    
    在这里插入图片描述
    6. 查bug1
    在这里插入图片描述在这里插入图片描述
    7. 查bug2
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sup_chao/article/details/84848237