简体   繁体   English

String.intern()如何工作

[英]String.intern() how to work

package com.zhb.jvm;

/**
 * 
 * @author zhb
 *
 */
public class RuntimeConstantPoolOOM {
    public static void main(String[] args){

        String str1 = "abc";
        System.out.println(str1.intern() == str1);    //true
        String str2 = new String("abcd");
        System.out.println(str2.intern() == str2);    //false

        String str3 =new StringBuilder("math").append("analyze").toString();
        System.out.println(str3.intern() == str3);    //true

        String str4 =new StringBuilder("computer").append("software").toString();
        System.out.println(str4.intern() == str4);    //true

        String str5 =new StringBuilder("jav").append("a").toString();
        System.out.println(str5.intern() == str5);    //false
    }

}

First of all,we can know the definiton of the intern() method. 首先,我们可以知道intern()方法的定义。 Definition for intern : When the intern method is invoked, if the pool already contains a string equal to thisString object as determined by the equals(Object) method, then the string from the pool is returned. intern的定义:调用intern方法时,如果池已经包含等于equals(Object)方法确定的thisString对象的字符串,则返回池中的字符串。 Otherwise, thisString object is added to the pool and a reference to this String object is returned. 否则,将thisString对象添加到池中,并返回对此String对象的引用。

str1.intern == str1 is true. str1.intern == str1为true。 this is easy to understand. 这很容易理解。 str2.intern() == str2 this is also easy to understand by the definition of the method. str2.intern()== str2这也很容易通过方法的定义来理解。 But why str3.intern() == str3 is true.in fact,I think it is false by the definition. 但是为什么str3.intern()== str3是正确的。实际上,我认为根据定义它是错误的。 There is a opposite thing that str5.intern() == str5 is false. 相反,str5.intern()== str5为假。 I run the command in the terminal java -version java version "1.7.0_40" Java(TM) SE Runtime Environment (build 1.7.0_40-b43) Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode) 我在终端java -version java版本“ 1.7.0_40”中运行命令Java™SE运行时环境(内部版本1.7.0_40-b43)Java HotSpot™64位服务器VM(内部版本24.0-b56,混合模式) )

I want to acquire the correct answer.thank you very much! 我想获得正确答案。非常感谢!

why str3.intern() == str3 is true 为什么str3.intern()== str3为true

Because, as you said: 因为,正如您所说:

Otherwise, thisString object is added to the pool and a reference to this String object is returned. 否则,将thisString对象添加到池中,并返回对此String对象的引用。

You're in that case. 你就是这种情况。 The pool doesn't contain str3 (ie "mathanalyze") yet. 该池尚不包含str3(即“ mathanalyze”)。 So str3 is added to the pool and returned. 因此将str3添加到池中并返回。

For str5, you're in the other case: 对于str5,您处于另一种情况:

if the pool already contains a string equal to thisString object as determined by the equals(Object) method, then the string from the pool is returned 如果池已经包含等于equals(Object)方法确定的thisString对象的字符串,则返回池中的字符串

So, the pool already contains the string "java" when your code is executed, which is not surprising since java is, for example, the name of the top-level package of all the standard classes, and also the name of the executable used to launch the JVM. 因此,执行代码时,池中已经包含字符串“ java”,这并不奇怪,因为java例如是所有标准类的顶级包的名称以及所使用的可执行文件的名称。启动JVM。 There is a huge chance that the literal string "java" is used in the code that bootstraps the application and loads classes before executing your main method. 在执行main方法之前,在用于引导应用程序并加载类的代码中很有可能会使用文字字符串“ java”。

The way I see it, I would say that the String "java" is by default in the pool. 我的看法是,池中默认为字符串"java" Indeed, when you call intern() on str3 , this word is not yet in the pool so it is added and the reference returned is str3 (no new object created), so the test gives true. 确实,当您在str3上调用intern()时,该词还没有在池中,因此将其添加,并且返回的引用为str3 (未创建新对象),因此测试得出true。 At the contrary, "java" is already in the pool so it returns the reference of the object in the pool, which is different from the reference of str5 . 相反, "java"已在池中,因此它返回池中对象的引用,这与str5的引用不同。

Note that you will observe the same behaviour not only with "java" but also with all the single characters. 请注意,您不仅会在使用"java"时观察到相同的行为,而且还会在所有单个字符中观察到相同的行为。

The test foo.intern() == foo is a way of measuring whether or not foo was already in the pool before intern() was called. 测试foo.intern() == foo是一种在调用intern()之前测量foo是否已经在池中的方法。 So str3.intern() == str3 means that str3 was not already in the pool. 因此, str3.intern() == str3表示str3尚未在池中。 That's all. 就这样。

There is probably a constant string "java" somewhere in the runtime that was loaded into the pool before your copy, which is why str5.intern() != str5 . 运行时中某个地方可能存在一个常量字符串"java" ,该常量字符串已在复制之前加载到池中,这就是为什么str5.intern() != str5

Here are the most obvious cases I found by grepping the OpenJDK 8 source code: 这是我通过grep OpenJDK 8源代码发现的最明显的情况:

./com/sun/beans/decoder/DocumentHandler.java:        setElementHandler("java", JavaElementHandler.class); // NON-NLS: the element name
./com/sun/tools/example/debug/gui/JDBMenuBar.java:        JDBFileFilter filter = new JDBFileFilter("java", "Java source code");
./com/sun/tools/jdi/SunCommandLineLauncher.java:                "java",
./sun/launcher/LauncherHelper.java:                (progname == null) ? "java" : progname ));
./sun/rmi/server/Activation.java:                        File.separator + "bin" + File.separator + "java";
./sun/rmi/server/Activation.java:                    command[0] = "java";

As I understand there might be any runtime string "java" , which causes this issue. 据我了解,可能存在任何运行时字符串“ java”,这会导致此问题。

    String str5 =new StringBuilder("jav").append("a").toString();
    System.out.println(str5.intern() == str5);    //false

These above two statements are only false , except any other string you want to form its passing with true . 上面这两个语句只是false ,除了要使用true构成其传递的任何其他字符串。

Intern () as per Java specification. 按照Java规范的Intern()。

This returns a canonical representation for the string object. 这将返回字符串对象的规范表示。 A pool of strings, initially empty, is maintained privately by the class String. 最初为空的字符串池由String类私有维护。 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. 调用intern方法时,如果池已经包含等于equals(Object)方法确定的此String对象的字符串,则返回池中的字符串。 Otherwise, this String object is added to the pool and a reference to this String object is returned. 否则,将此String对象添加到池中,并返回对此String对象的引用。 It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. 因此,对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern()== t.intern()为true。

All literal strings and string-valued constant expressions are interned. 所有文字字符串和字符串值常量表达式均已插入。 String literals are defined in section 3.10.5 of the The Java™ Language Specification. 字符串文字是在Java™语言规范的3.10.5节中定义的。

Returns : a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings. 返回 :具有与该字符串相同的内容的字符串,但保证来自唯一字符串池。

Hope it will help you. 希望对您有帮助。

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

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