简体   繁体   English

String.intern()的返回解释

[英]The return of String.intern() explained

Consider: 考虑:

String s1 = new StringBuilder("Cattie").append(" & Doggie").toString();
System.out.println(s1.intern() == s1); // true why?
System.out.println(s1 == "Cattie & Doggie"); // true another why?

String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2); // false

String s3 = new String("Cattie & Doggie");
System.out.println(s3.intern() == s3); // false
System.out.println(s3 == "Cattie & Doggie"); // false

I got confused why they are resulting differently by the returned value of String.intern() which says: 我很困惑为什么它们由于String.intern()返回值而产生不同的结果 ,它说:

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. 调用实习方法时,如果池已经包含等于此字符串对象的字符串(由equals(Object)方法确定),则返回池中的字符串。 Otherwise, this String object is added to the pool and a reference to this String object is returned. 否则,将此String对象添加到池中,并返回对此String对象的引用。

Especially after these two tests: 特别是经过这两项测试:

assertFalse("new String() should create a new instance", new String("jav") == "jav");
assertFalse("new StringBuilder() should create a new instance",
    new StringBuilder("jav").toString() == "jav");

I once read a post talking about some special strings interned before everything else, but it's a real blur now. 我曾经读过一篇文章,谈论在其他事情之前被拘留的一些special strings ,但现在它真的很模糊。

If there are some strings pre-interned , is there a way to get kind of a list of them? 如果pre-interned存在一些字符串,是否有办法获得它们的列表? I am just curious about what they can be. 我只是好奇他们会是什么。


Updated 更新

Thanks to the help of @Eran and @Slaw, I finally can explain what just happened there for the output 感谢@Eran和@Slaw的帮助,我终于可以解释输出中刚刚发生了什么

true
true
false
false
false
  1. Since "Cattie & Doggie" doesn't exist in the pool, s1.intern() will put the current object reference to the pool and return itself, so s1.intern() == s1 ; 由于"Cattie & Doggie"不存在"Cattie & Doggie" ,s1.intern()会将当前对象引用放入池中并返回自身,因此s1.intern() == s1 ;
  2. "Cattie & Doggie" already in the pool now, so string literal "Cattie & Doggie" will just use the reference in pool which is actually s1 , so again we have true ; "Cattie & Doggie"现在已经在游泳池中,所以字符串文字"Cattie & Doggie"将只使用池中的引用,实际上是s1 ,所以我们再次true ;
  3. new StringBuilder().toString() will create a new instance while "java" is already in the pool and then the reference in pool will be returned when calling s2.intern() , so s2.intern() != s2 and we have false ; new StringBuilder().toString()将创建一个新实例,而"java"已经在池中,然后在调用s2.intern()时将返回池中的引用,所以s2.intern() != s2和我们有false
  4. new String() will also return a new instance, but when we try to s3.intern() , it will return the previously stored reference in the pool which is actualy s1 so s3.intern() != s3 and we have false ; new String()也将返回一个新实例,但是当我们尝试s3.intern() ,它将返回池中先前存储的引用,该引用实际上是s1所以s3.intern() != s3并且我们有false ;
  5. As #2 already discussed, String literal "Cattie & Doggie" will return the reference already stored in the pool (which is actually s1 ), so s3 != "Cattie & Doggie" and we have false again. 正如#2已经讨论过的那样,字符串文字"Cattie & Doggie"将返回已经存储在池中的引用(实际上是s1 ),所以s3 != "Cattie & Doggie" ,我们又false了。

Thanks for @Sunny to provide a trick to get all the interned strings. 感谢@Sunny提供了获取所有interned字符串的技巧。

s2.intern() would return the instance referenced by s2 only if the String pool didn't contain a String whose value is "java" prior to that call. 仅当String池在该调用之前不包含值为“java”的Strings2.intern()才会返回s2引用的实例。 The JDK classes intern some String s before your code is executed. JDK类在执行代码之前实际执行一些String "java" must be one of them. “java”必须是其中之一。 Therefore, s2.intern() returns the previously interned instance instead of s2 . 因此, s2.intern()返回先前实例化的实例而不是s2

On the other hand, the JDK classes did not intern any String whose value is equal to "Cattie & Doggie", so s1.intern() returns s1 . 另一方面,JDK类没有实现任何其值等于“Cattie&Doggie”的String ,因此s1.intern()返回s1

I am not aware of any list of pre-interned Strings. 我不知道任何预先实习的字符串列表。 Such a list will most likely be considered an implementation detail, which may vary on different JDK implementations and JDK versions, and should not be relied on. 这样的列表很可能被认为是一个实现细节,它可能因不同的JDK实现和JDK版本而有所不同,不应该依赖。

When the intern() method is invoked on a String object it looks the string contained by this String object in the pool, if the string is found there then the string from the pool is returned. 当在String对象上调用intern()方法时,它会查找池中此String对象包含的字符串,如果在那里找到该字符串,则返回池中的字符串。 Otherwise, this String object is added to the pool and a reference to this String object is returned. 否则,将此String对象添加到池中,并返回对此String对象的引用。

So java string must already be in the pool. 所以java字符串必须已经在池中。 hence it is giving false. 因此它是虚假的。

You can print all strings in pool 您可以在池中打印所有字符串

How to print the whole String pool? 如何打印整个String池?

Here is an example to get all string if you are using openjdk . 以下是使用openjdk获取所有字符串的示例

String literals (those that are hardcoded like "a string") are already interned for you by the compiler. 字符串文字(像“字符串”这样硬编码的字符串文字)已由编译器为您实现。 But those strings that are acquired programmatically are not, and will be interned only if you use .intern() method. 但是那些以编程方式获取的字符串不会,并且只有在使用.intern()方法时才会被实现。

Usually you don't intern strings manually, unless you know you will store in memory a large number of repeating strings, so you can save a lot of memory that way. 通常你不会手动实习字符串,除非你知道你将在内存中存储大量重复字符串,这样你就可以节省大量内存。

That is explained here: What is Java String interning? 这里解释了: Java String interning是什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM