深入理解java虚拟机遇到的问题(一) String.intern()的学习

在阅读深入理解java虚拟机的时候看到了如下代码,不理解String.intern()。

第一个结果为true,第二个结果为false。

于是阅读了这篇文章https://blog.csdn.net/soonfly/article/details/70147205,其中遇到一些问题。

上代码

String str2 = new String("str")+new String("01");
str2.intern();
String str1 = "str01";
System.out.println(str2==str1);

结果为true。

String str2 = new String("str01");
str2.intern();
String str1 = "str01";
System.out.println(str2==str1);

结果为false。

问题来了,把第一个代码创建字符串合到一起为什么就是false了?两者有什么区别?

先说明一下 String str = new String("xxx")和 String str = “xxx”的区别

String  a = new String( "Hello"),jvm首先在字符串常量池内里面看看能不能找到字符串 "Hello ",如果找到,不做任何事情,否则,创建新的string对象,放到字符串常量池里面。由于遇到了new,还会在堆上创建string对象存储 "Hello ",并将引用返回给s2。(注:先在常量池里进行创建,再在堆中创建字符串)。

String b = "Hello",jvm首先在常量池内里面看找不找到字符串 "Hello ",找到,返回他的引用给b,否则,创建新的string对象,放到string池里,并返回引用。

答案:

第一段代码先检查常量池里面有没有字符串“str”和“01”,由于没找到,所以先在常量池里创建两个字符串常量 “str”和“01”(创建两个,并不是一个“str01”),然后在堆中创建“str”和“01”。最后将堆中的new String("str")和new String("01") 返回的引用组合起来返回给str2。

调用str2.intern(),由于常量池里面没有字符串“str01”,所以根据intern()方法,将在常量池中生成(“str”和“01”)在堆中的引用。(其实就是把两个字符串的地址拼接起来放到常量池中)。

String str1 = “str01”,因为常量池中有了字符串“str01”,所以返回堆中的引用。最终的结果为true。

第二段代码会先在常量池中创建字符串“str01”,然后在堆中创建,并返回堆中的引用。

调用str2.intern(),由于常量池已经存在,不会做任何事。

String str1 = “str01”,由于常量池已经存在,返回在常量池中的引用。str1(常量池引用)和str2(堆中引用)不一样,返回false。

注释:

常量池在jdk 1.7以前,常量池在方法区中,1.7之后在堆中开辟一块内存,存放常量池。

String.intern()方法:

jdk1.7之前,intern方法先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,不存在,将字符串的实例复制到常量池中,并返回常量池中的引用。

jdk1.7之后,intern方法先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,不存在,而只是在常量池中生成一个对原字符串的引用。(将堆中的引用放到常量池中存储) 。

还有一个问题不是很理解,书中所说java这个字符串在执行StringBuilder.toString()之前已经出现过,常量池已经有了它的引用,所以返回false。莫非常量池自带字符串“java”?

答案在:https://blog.csdn.net/w605283073/article/details/72753494

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Java 中,String.intern() 方法会返回字符串对象在虚拟机的字符串池中的引用(如果池中已经包含了一个等于此 String 对象的字符串),否则,它会将此 String 对象添加到池中,并且返回对此 String 对象的引用。字符串池是一个由 String 对象组成的集合,用于存储在程序中反复使用的字符串。使用字符串池可以减少字符串对象的数量,从而节省内存空间。 举个例子: ``` String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); System.out.println(s1 == s2); // true System.out.println(s1 == s3); // false s3 = s3.intern(); System.out.println(s1 == s3); // true ``` 在上面的代码中,由于 s1 和 s2 是相同的字面值,所以它们指向的是同一个字符串对象。但是 s3 是通过 new 运算符创建的新对象,所以 s1 和 s3 不是同一个对象。但是通过调用 s3.intern() 方法并将返回值赋给 s3,s3 就指向了字符串池中的 "Hello" 字符串,所以 s1 和 s3 指向的是同一个对象。 ### 回答2: Twitter是一家全球著名的社交媒体平台,通过推文(tweets)的方式使用户能够分享自己的想法、看法、图片和链接等内容。String.internJava中的一个方法,用于在运行时将字符串实例添加到内部字符串池中,并返回对该字符串实例的引用。 在Twitter的背后,有一个庞大的后台系统,用于处理大量的用户数据和内容。在这个系统中,处理字符串是非常常见的操作,因此String.intern方法在这里也发挥了重要的作用。 Twitter对String.intern的使用主要是为了优化内存和提高性能。由于用户在推文中频繁使用相同的字符、词语和短语,将这些重复的字符串实例添加到内部字符串池中可以减少内存消耗。而使用String.intern方法的返回值作为字符串的引用,可以提高字符串的比较效率,从而提高整个系统的性能。 除了内存和性能方面的优化,String.intern还能够在字符串比较时保证唯一性。当多个线程或不同的部分都使用了String.intern方法来获取字符串的引用时,它们得到的引用都是相同的。这样可以有效地避免同样的字符串被多次创建,并且可以确保在比较字符串时得到正确的结果。 综上所述,Twitter对String.intern的使用是为了优化内存、提高性能以及确保字符串的唯一性。通过将重复的字符串实例添加到内部字符串池中,并使用String.intern方法返回的引用来进行字符串的操作,Twitter能够更高效地处理用户的大量数据和内容,提供更好的用户体验。 ### 回答3: Twitter对于String.intern()的使用要根据不同的情况。String.intern()方法会在字符串常量池中查找是否存在相同值的字符串,如果存在则返回该字符串的引用,否则将该字符串添加到常量池中并返回引用。 在Twitter中,由于字符串的高频使用,使用String.intern()可以带来一些好处。首先,由于常量池中的字符串只会存在一份,使用intern()可以节省内存空间。对于一些频繁创建的字符串对象,如标识符、URL等,通过intern()方法可以使这些对象在内存中只存在一份,从而减少内存占用。 其次,使用String.intern()可以提高字符串的比较效率。由于常量池中的字符串只存在一份,使用intern()方法可以通过引用比较来判断字符串是否相等,而不需要逐个字符比较的过程。这对于Twitter这样的大规模社交平台来说,可以在处理大量文本数据时提高效率。 然而,需要注意的是,对于较短的字符串或者不频繁使用的字符串,使用intern()可能造成性能损失。String.intern()方法需要在常量池中进行查找和添加操作,这可能会消耗一定的时间和资源。因此,在使用intern()方法时需要权衡利弊,并根据实际情况来决定是否使用。 综上所述,Twitter在高频使用字符串的情况下,可以考虑使用String.intern()方法来节省内存和提高效率。但需要注意的是,在使用时需要根据具体情况进行权衡,并在性能损失较大的情况下避免使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值