可变对象(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流 ...
随机推荐
- Linux 命令 -- chmod
chmod命令用来变更文件或目录的权限.在UNIX系统家族里,文件或目录权限的控制分别以读取.写入.执行3种一般权限来区分,另有3种特殊权限可供运用.用户可以使用chmod指令去变更文件与目录的权限, ...
- jQuery 的动画效果图片----隐藏打开方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [转]what’s the difference between @Component ,@Repository & @Service annotations in Spring
原文地址:https://www.cnblogs.com/softidea/p/6070314.html @Component is equivalent to <bean> @Servi ...
- SEO学习
一.什么是SEO SEO是由英文Search Engine Optimization缩写而来, 中文意译为“搜索引擎优化”!SEO是指通过对网站进行站内优化(网站结构调整.网站内容建设.网站代码优化等 ...
- The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter.
The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the assoc ...
- 网站大于10M的视频不能播放
IIS配置的网站,添加了几个mp4视频,有个可以正常播放,有的却不加载不出来,提示错误: net::ERR_CONNECTION_ABORTED 网上有文章说是由于安全狗bug导致,下载安装一个补丁覆 ...
- jquery对象与核心函数
原生js入口函数与jQuery入口函数的区别 1.window.onload与document.ready在加载时间上的差异 document.ready会先触发,其次才是window.onload ...
- 原生JS的轮播图
学习前端也有一小段时间了,当初在学习javascript的时候,练手的一个轮播图实例,轮播图也是挺常见的了. 着是通过获取图片偏移量实现的.也实现了无缝切换.还有一点问题就是没有加上图片切换的时候的延 ...
- Mybatis学习随笔
学习Mybatis路径(适合有java基础和mysql基础的小伙伴) 1.把项目搭建起来,跑一跑感受一下 2.测试基本映射 3.测试高级映射 4.测试动态sql 5.学习懒加载与缓存 6.与sprin ...
- servlet中cookie和session操作
1.1 软件中的会话 一次会话: 打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器 登录场景: 打开浏览器 -> 浏览到登陆页面 -> 输入用户名和密码 -> 访问 ...