String s和newString,有很大区别,90%的java程序员都不知道

一般对象都是通过 new 关键字生成的,但是 String 还有第二种生成方式,也就是我们经常使用的直接申明方式,比如:String str = "a",即是通过直接量 "a" 进行赋值的。对于String 对象来说,这种方式是极力推荐的,但不建议使用 new String("a") 的方式赋值。为什么呢?

我们来看一段程序:

注意看上边的程序,我们使用 "==" 判断的是两个对象的引用地址是否相同,也就是判断是否为同一个对象,打印结果是 true,fasle,true。即有两个直接量是同一个对象(经过intern 处理后的String与直接量是同一个对象),但是直接通过new 生成的对象却与之不相等,原因何在?

原因是Java 为了避免在一个系统中大量产生 String 对象(为什么会大量产生?因为String 字符串是程序中最经常使用的类型),于是就设计出了一个字符串池(也叫做字符串常量池,String Pool 或 String Constant Pool 或 String Literal Pool),在字符串池中所容纳的都是 String 字符串对象,它的创建机制是这样的:

创建一个字符串时,首先检查池中是否有字面值相等的字符串,如果有,则不再创建,直接返回池中该对象的引用,若没有则创建,然后放到池中,并返回新建对象的引用,这个池和我们平常所说的池概念非常相似。对于此例子来说,就是在创建第一个"中国"字符串时,先检查字符串池中有没有该对象,发现没有,于是就创建了"中国"这个字符串并放到池中,待在创建str2字符串时,由于池中已经有了该字符串,于是就直接返回了该对象的引用,此时,str1 和 str2 指向的是同一个地址,所以使用 "==" 来判断那当然是相等了。

那为什么使用 new String("中国") 就不相等了呢?因为直接声明一个 String 对象是不检查字符串池的,也不会吧对象放到池中,那当然 "==" 为 false 了。

那为什么使用 intern 方法处理后就又相等了呢?因为 intern 会检查当前的对象在对象池中是否有字面值相同的引用对象,如果有则返回池中对象,如果没有则放置到对象池中,并返回当前对象。

可能有码农同学要问了,对象放到池中会不会产生线程安全问题呀?好问题,不过Java已经考虑到了,String 类是一个不可变对象其实有两层意思:一是 String 类 是 final类,不可继承,不可能产生一个 String的子类;二是在 String 类提供的所有方法中,如果有String返回值,就会新创建一个 String对象,不对原对象进行修改,这也就保证了原对象是不可改变的。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180126A0HQS000?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券