咨询热线:15821890032 联系人:周祥冬 地址:江西省南昌市南昌市东湖区昌东二路
String 与不可变对象
来源:salon365官方线路 发布时间:2019-11-18 点击量:11
什么是不可变对象 ?不可变对象指的是在创建一个对象之后 ,不能再改变它的状态 ,那么这个对象就是不可变的 。不能改变状态的意思是 ,不能改变对象内的成员变量 ,包括基本数据类型的值不能改变 ,引用类型的变量不能指向其它的对象 ,引用类型指向的对象状态也不能改变 。
这里插播一下对象和对象的引用之间的区别 ,对象的引用是放在栈中的 ,而对象是放在堆中的 ,看这个例子 String s = "123" ; s = "456"
; 表面上 s 看是变了 ,但是要搞清楚 ,变的只是 String 对象的引用 s ,而 “123” 这个对象是没有变化的 。看一个图 :
我们都说 String 是不可变对象 ,那我们就分析一下 String 的源码来看看它是怎么保证 String 对象不可变的 。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 public String(String original) { this.value = original.value; this.hash = original.hash; } public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); } public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } ...
我们通过分析源码可知 ,首先 String 类和存放字符串的 char 型数组都是 final 类型的 ,保证了 String 类不能被继承 ,value 这个引用本身不会该变 ,但是这样还不能说明属性是不可变的 ,因为我们可以通过改变 value 数组中具体的值来达到改变 value 的目的 。
public static void main(String[] args) { char[] value = {"a","b","c","d"}; System.out.println(value); for (int i = 0; i < value.length; i++) { if(i == 1){ value[i] = "B"; } } System.out.println(value); //aBcd }
但是进一步研究会发现 ,对于 value 这个属性 ,被定义为 private ,而且 String 并没有提供相对应的 get set 方法 ,所以我们也不能操作它 。而那些我们常认为改变了 String 对象的方法 ,比方说 subString concat toUpperCase tirm 看了源码之后发现 ,这些方法都是重新创建了一个 char 数组 ,并没有改动之前的对象 。这也就是我们常说 String 是不可变对象的原因 。但是我们还是可以通过反射的方式来改变 value 的值 ,看个例子就好 ,但是我们一般不这么做 。
public static void main(String[] args) throws Exception { //创建字符串"Hello World", 并赋给引用s String s = "Hello World"; System.out.println("s = " + s); //Hello World //获取String类中的value字段 Field valueFieldOfString = String.class.getDeclaredField("value"); //改变value属性的访问权限 valueFieldOfString.setAccessible(true); //获取s对象上的value属性的值 char[] value = (char[]) valueFieldOfString.get(s); //改变value所引用的数组中的第5个字符 value[5] = "_"; System.out.println("s = " + s); //Hello_World }
为什么要将 String 设计为不可变对象呢 ?当然是为了提高效率和安全 ,也是由于 String 的超高使用频率 。效率主要体现在当我们复制 String 对象的时候我只需要复制引用即可 ,不需要复制具体的对象 ,而在多线程环境中 ,若是不同的线程同时修改 String 对象 ,相互之间也不会有影响 。因为一旦改变都会创建一个新的字符串 ,保证了线程的安全 。
另外在堆中有个字符串常量池 ,我们创建的字符串都会存在这里 ,当创建相同的字符串的时候 ,其实指向的是同一个地方 。这就节省了大量的空间 ,当然 ,能出现字符串常量池也是因为 String 是不可变对象 。
因为 String 不可变 ,所以在创建对象的时候就已经将 hashCode 的值计算出来缓存在字段 hash 中 。这样在 Map 中 String 就很适合作为主键 ,速度快 。(因为在散列表中我们定位时会计算主键的 hash 值 。)
/** Cache the hash code for the string */ private int hash; // Default to 0
还有在数据库连接的时候我们通过字符串来传递用户名 ,密码 ,连接的库等信息 ,若字符串可变 ,则很可能被黑客篡改 。
PS. 基本类型对应的包装类都是不可变对象 ,这样设计的原因还是因为使用太频繁 ,好处在上面已经说过了 。突然感觉学到了好多之前没注意到的细节 。
源码版本为 JDK 1.7
推荐阅读:https://www.cnblogs.com/YJK923/p/9479805.html
参考资料:https://zhuanlan.zhihu.com/p/38144507
相关产品
-
【环球网报道 记者 王莉兰】据法国国际广播电台8月2日报道,利比亚东部班加西发生针对安全部队的汽车炸弹袭击。法新社消息称,袭击行动造成22人死亡,20人受伤。
-
上半年,英雄互娱净利润为2.25亿元,同比增长3111.21%,毛利率为88.91%,在游戏上市公司“朋友圈”中崭露头角。英雄互娱上半年实现营收3.77亿元,同比增长4728.94%。
-
据美国《基督教科学箴言报》8月3日报道,近日美国国会未能通过处于风口浪尖的移民法案,其中一大原因为美国政治体系中可行使否决权的部门过多,不利于政策实施。
-
那届世界杯中,威尔士国家队在小组赛里与墨西哥队、匈牙利队、瑞典队战成三连平,通过附加赛战胜匈牙利队出线(即八强),却在出线后就碰到了当届冠军巴西队,以0比1负于对手。而那场比赛踢进唯一进球的,就是当年只有17岁的贝利,这也是贝利在国际比赛中的首个进球。所以后来有一本书就是以此为题:《当贝利让我们心碎:威尔士与1958年世界杯》。
-
在他看来,这已经威胁到了华为、新华三的地盘,“原来是它玩它的,我玩我的,现在它已经打到我地盘了。这是我们公有云最基本的一个战略,就是它打到我地盘了,我必须有还手之力。”
-
记者注意到,前两轮调价周期油价均为上调,这意味着本轮实现了“三连涨”,且此轮油价上调幅度为年内最大涨幅。至此,2018年国内油价经历“五涨二跌一搁浅”格局,汽油累计上调365元/吨,柴油累计上调350元/吨。
-
在北上广每天发生的故事有太多,拥有的、错过的、遗憾的、满足的。故事中的主人公有着许多曾在他乡打拼过的青年们的缩影。背井离乡,别离亲人,寻找机会,向往成功,但凡向前看的人,哪个何尝不是呢?只是有行动还是没行动而已。北漂故事加上《后来》再加上观众本身的故事,想必有点文艺细胞或者情感阅历的人,观影过程中手、纸巾、袖口会有一个要用到。
-
有人说导游这个职业“睡得比狗晚,起得比鸡早,吃得比猪差”,这话一点不夸张,如果不进入这个行业,很难有人体会得到导游身体和心理两方面的劳困。
热点资讯
- 极限大挑战《梦想世界》国庆活动预告2019-11-09
- ASP.NETMVC从空项目开始定制项目2019-06-24
- 《指环王》官方授权MMORPG新作曝光将由国内团队研发2019-11-15
- 高通:它正在收集非法销售苹果手机的证据,并在本周内提交法院。2019-06-24
- ‘98월드컵’지단유니폼,최대5,149만원경매...역대최고는?2019-06-24
- 中国液化天然气生产者价格飙升2019-11-05
- 拒绝臃肿/可选加绒,雷森思旗舰店男士九分弹力休闲裤28元(40元券)2019-11-12
- 把学生介绍到校外不合格的培训机构:小学校长受到批评|激增的新闻|校长|培训机构2019-06-24