可变对象(immutable)和不可变对象(mutable)
可变对象(immutable)和不可变对象(mutable)
这个是之前一直忽略的一个知识点,比方说说起String为什么是一个不可变对象,只知道因为它是被final修饰的所以不可变,而没有抓住不可变三个字的重点:
1、不可变对象就是那些一旦被创建,它们的状态就不能被改变的对象,每次对它们的改变都是产生了新的对象
2、可变对象就是那些创建后,状态依然可以被改变的对象
举个例子:String和StringBuilder,String是不可变的,因为每次对String对象的修改都将产生一个新的String对象,而原来的对象保持不变;StringBuilder是可变的,因为每次对StringBuilder的修改都作用于该对象本身,并没有新的对象产生。如果这么说还不够清楚,截取两段源码,首先是String的concat方法,用户向已有的字符串后面拼接新的字符串:

1 public String concat(String str) {
2 int otherLen = str.length();
3 if (otherLen == 0) {
4 return this;
5 }
6 char buf[] = new char[count + otherLen];
7 getChars(0, count, buf, 0);
8 str.getChars(0, otherLen, buf, count);
9 return new String(0, count + otherLen, buf);
10 }

看到第9行,new了一个新的String出来。然后看一下StringBuilder,StringBuilder最常用的应该就是append方法了,append一个字符串的时候会调用StringBuilder的父类AbstractStringBuilder的append方法:

1 public AbstractStringBuilder append(String str) {
2 if (str == null) str = "null";
3 int len = str.length();
4 ensureCapacityInternal(count + len);
5 str.getChars(0, len, value, count);
6 count += len;
7 return this;
8 }

第5行的这个value就是一个char型数组"char[] value;",每次对StringBuilder的操作都是对value的改变。
不可变的对象对比可变对象有两点优势:
1、保证对象的状态不被改变
2、不使用锁机制就能被其他线程共享
实际上JDK本身就自带了一些不可变类,比如String、Integer、Float以及其他的包装类,判断的方式就是看它们真正的那个对象是不是final的就好了。
我们自己也可以创建不可变对象,创建不可变对象应该遵循几个原则:
1、不可变对象的状态在创建之后就不能发生改变,任何对它的改变都应该产生一个新的对象
2、不可变对象的所有属性应该都是final的
3、对象必须被正确地创建,比如对象引用在创建过程中不能泄露
4、对象应该是final的,以此来限制子类继承父类,以避免子类改变了父类的不可变特性
使用不可变类的好处:
1、不可变类是线程安全的,可以不被synchronized修饰就在并发环境中共享
2、不可变对象简化了程序开发,因为它无需使用额外的锁机制就可以在线程之间共享
3、不可变对象提高了程序的性能,因为它减少了synchronized的使用
4、不可变对象时可以被重复利用的,你可以将它们缓存起来,就像字符串字面量和整型数值一样,可以使用静态工厂方法来提供类似于valueOf这样的方法,它可以从缓存中返回一个已经存在的不可变对象,而不是重新创建一个
不可变对象虽然好,但是它有一个很大的缺点就是会制造出大量的垃圾,给垃圾收集带来很大的麻烦,由于它们不能被重用而且,所以不可变对象的使用依赖于开发人员合理的使用。另外,不可变对象也有一些安全问题,比如密码就建议不要用String,因为:
如果密码是以明文的形式保存成字符串 ,那么它将一直留在内存中,直到垃圾收集器把它清除。而由于字符创被放在字符串缓存池中以方便重用,所以它就可以在内存中被保留很长时间,而这将导致安全隐患,因为任何能够访问内存的人都可以清晰地看到文本中的密码,这也是为什么总是应该用加密的形式而不是明文来保存密码。由于字符串是不可变的,所以没有任何方式可以修改字符串的值,因为每次修改都将产生新的字符串,而如果使用char[]来保存密码,就可以将其中所有元素都设置为空或者是零。所以将密码保存到字符数组中很明显地降低了密码被窃的风险。
可变对象(immutable)和不可变对象(mutable)的更多相关文章
- Java 的不可变类 (IMMUTABLE CLASS) 和 可变类 (MUTABLE CLASS)
一.简单定义不可变对象(Immutable Objects)即对象一旦被创建,它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects).当满足以下条件时,对 ...
- Java学习之String对象为什么是不可变的
转自:http://www.2cto.com/kf/201401/272974.html,感谢作者的总结 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变 ...
- Immutable(不可变)集合
不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对象有以下的优点: 对不可靠的客户代 ...
- JAVA不可变类(immutable)机制与String的不可变性
一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类, ...
- 【Java基础】JAVA不可变类(immutable)机制与String的不可变性
一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String(8种基本数据类型的包装类和S ...
- JAVA不可变类(immutable)机制与String的不可变性--非常好.
JAVA不可变类(immutable)机制与String的不可变性 https://www.cnblogs.com/jaylon/p/5721571.html
- js 不可变的原始值和可变的对象引用
javascript中的原始值(undefined.null.布尔值.数字和字符串)与对象(包括数组和函数)有着根本区别.原始值是不可更改的:任何方法都无法更改(或“突变”)一个原始值.对数字和布尔值 ...
- java IO之 序列流 集合对象Properties 打印流 流对象
序列流 也称为合并流. SequenceInputStream 序列流,对多个流进行合并. SequenceInputStream 表示其他输入流的逻辑串联.它从输入流的有序集合开始,并从 第一个输入 ...
- ActiveMQ服务器之间传输对象,项目A发送对象到项目B接收发送对象《二》
ActiveMQ服务器之间传输对象,项目A发送对象到项目B接收发送对象<一> 上一篇文章写到对象之间传输使用线程方式 ,无法使用监听方式,最近解决了使用监听方式接收对象,本次使用配置文件方 ...
- 什么是可变参数?如何创建不可变集合?Steam三类方法是什么?获取流方法特点?流中间方法特点?终结流方法特点?
==知识梳理== ==重难点梳理== ==今日目标== 1.能够了解什么是可变参数 2.能够了解如何去创建不可变集合 3.能够掌握Stream流的使用 ==知识点== 1.可变参数 2.Stream流 ...
随机推荐
- React.js 小书 Lesson24 - PropTypes 和组件参数验证
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson24 转载请注明出处,保留原文链接和作者信息. 我们来了到了一个非常尴尬的章节,很多初学的朋友 ...
- win10中VirtualBox联网设置
<分享>关于win10操作系统中VirtualBox无法桥接的解决方法 版权声明:本文为博主原创文章,未经博主允许不得转载. 升级win10,本来是一件很好的事,想好好体验一下新版本的感觉 ...
- ExtJs6编译之后上线报错无法查看到的解决方法
最近Extjs编译后部署遇到了一个错误c is not a constructor,报错位置在app.js里,这根本没法找 解决方法:用命令sencha app build testing 编译之后, ...
- 2017年12月14日 LinQ高级查&&Asp.net WebForm Asp.net MVC
LinQ的高级查询用法 开头:StartsWith()结尾:EndsWith()模糊:Contains() 个数:Count最大值:Max(r => r.price)最小值:Min(r => ...
- 关于eclipse的编码注释等Code Template设置
啥也不说直接放东西: 首先进入eclipse的preferences里的java 点击Insert variable可以自己设置需要的 1. 设置Files:点击edit, /** * <p&g ...
- C Primer Plus note8
error: too few arguments to function 'imax'| 运行上面的代码,产生了下面的错误: 中文翻译是:函数imax()中的参数太少. 查看imax()函数声明,发现 ...
- lintcode 题目记录3
Expression Expand Word Break II Partition Equal Subset Sum Expression Expand 字符串展开问题,按照[]前的数字展开字符 ...
- Maven pom.xml 常用打包配置
<build> <!-- 指定JAVA源文件目录 --> <sourceDirectory>src</sourceDirectory> <!-- ...
- BZOJ3992: [SDOI2015]序列统计(NTT 原根 生成函数)
题意 题目链接 给出大小为\(S\)的集合,从中选出\(N\)个数,满足他们的乘积\(\% M = X\)的方案数 Sol 神仙题Orz 首先不难列出最裸的dp方程,设\(f[i][j]\)表示选了\ ...
- poj 1679 The Unique MST (判定最小生成树是否唯一)
题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total S ...