String intern()的作用

Strings are a fundamental part of any modern programming language, every bit as important as numbers. So you‘d think that Java programmers would go out of their way to have a solid understanding of them -- and sadly, that isn‘t always the case.

I was going through the source code to Xerces (the XML parser included in Java) today, when I found a very surprising line:

com.sun.org.apache.xerces.internal.impl.XMLScanner:395
protected final static String fVersionSymbol = "version".intern();

There are a number of strings defined like this, and every one of them is being interned. So what exactly is intern()? Well, as you no doubt know, there are two different ways to compare objects in Java. You can use the == operator, or you can use the equals() method. The == operator compares whether two references point to the same object, whereas the equals() method compares whether two objects contain the same data.

One of the first lessons you learn in Java is that you should usually use equals(), not ==, to compare two strings. If you compare, say, new String("Hello") == new String("Hello"), you will in fact receive false, because they are two different string instances. If you use equals() instead, you will receive true, just as you‘d expect. Unfortunately, the equals() method can be fairly slow, as it involves a character-by-character comparison of the strings.

Since the == method compares identity, all it has to do is compare two pointers to see if they are the same, and obviously it will be much faster thanequals(). So if you‘re going to be comparing the same strings repeatedly, you can get a significant performance advantage by reducing it to an identity comparison rather than an equality comparison. The basic algorithm is:

1) Create a hash set of Strings
2) Check to see if the String you‘re dealing with is already in the set
3) If so, return the one from the set
4) Otherwise, add this string to the set and return it

After following this algorithm, you are guaranteed that if two strings contain the same characters, they are also the same instance. This means that you can safely compare strings using == rather than equals(), gaining a significant performance advantage with repeated comparisons.

Fortunately, Java already includes an implementation of the algorithm above. It‘s the intern() method on java.lang.Stringnew String("Hello").intern() == new String("Hello").intern() returns true, whereas without the intern() calls it returns false.

So why was I so surprised to see protected final static String fVersionSymbol = "version".intern(); in the Xerces source code? Obviously this string will be used for many comparisons, doesn‘t it make sense to intern it?

Sure it does. That‘s why Java already does it. All constant strings that appear in a class are automatically interned. This includes both your own constants (like the above "version" string) as well as other strings that are part of the class file format -- class names, method and field signatures, and so forth. It even extends to constant string expressions: "Hel" + "lo" is processed by javac exactly the same as "Hello", and "Hel" + "lo" == "Hello" will returntrue.

So the result of calling intern() on a constant string like "version" is by definition going to be the exact same string you passed in. "version" == "version".intern(), always. You only need to intern strings when they are not constants, and you want to be able to quickly compare them to other interned strings.

There can also be a memory advantage to interning strings -- you only keep one copy of the string‘s characters in memory, no matter how many times you refer to it. That‘s the main reason why class file constant strings are interned: think about how many classes refer to (say) java.lang.Object. The name of the class java.lang.Object has to appear in every single one of those classes, but thanks to the magic of intern(), it only appears in memory once.

The bottom line? intern() is a useful method and can make life easier -- but make sure that you‘re using it responsibly.

摘自:https://weblogs.java.net/blog/enicholas/archive/2006/06/all_about_inter.html

时间: 2024-11-05 11:45:51

String intern()的作用的相关文章

JDK源码学习(2)-String.intern()方法详解

1.方法intern()为java内部方法,如下  public native String intern(); native方法为通过jvm进行运行,jdk8中隐藏了该方法的具体处理方法. 2.作用:该方法注释为 "如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回". 3.测试代码一 public static void main(String[] args) { String s1 = new String(&

关于 String.intern()

String.intern() 实际上会返回第一次生成该 String 内容的那个实例. 所谓内容就是 "abc", "123" 这个字符串的内容 1. String s1 = "a"; ([email protected]) 那么 s1 就是第一次生成内容 "a" 的实例 @100, 所以如果 String s1 = "a"; ([email protected]) String s2 = "a

String放入运行时常量池的时机与String.intern()方法解惑

运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念,包括了下面三类常量: - 类和接口的全限定名(包名+类名) - 字段的名称和描述符 - 方法的名称和描述符 运行时常量池位置 运行时常量池在JDK1.6及之前版本的JVM中是方法区的一部分,而在HotSpot虚拟机中方法区放在了"永久代(Permanent Generation)".所以

Java提高篇——理解String 及 String.intern() 在实际中的应用

1. 首先String不属于8种基本数据类型,String是一个对象.   因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. new String()和new String("")都是申明一个新的空字符串,是空串不是null: 3. String str="kvill":  String str=new String ("kvill");的区别: 在这里,我们不谈堆,也不谈

String.Intern 方法 (String)

public static string Intern(string str) 参数 str 要在暂存池中搜索的字符串. 返回值 Type: System.String 如果暂存了 str,则返回系统对其的引用:否则返回对值为 str 的字符串的新引用. 一.字符串拘留池的引入 在一个程序中,如果将同一个字符串赋值给不同的字符串引用,那么系统会为多次分配内存空间,然而这些内存中存储的是同一个字符串(见下图).这不仅浪费了宝贵的内存,还极大程度的降低了系统的性能.为了改善程序的性能,.net提出了

对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法

在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普遍的时候),类几乎是"静态的"并且很少被卸载和回收,因此类也可以被看成"永久的".另外由于类作为JVM实现的一部分,它们不由程序来创建,因为它们也被认为是"非堆"的内存. 在JDK8之前的HotSpot虚拟机中,类的这些"永久的"

synchroized String object 时使用guava的interner代替String.intern()

synchroized代码块, 直接使用String作为lock的时候,不会起作用 此时可已使用String.intern()作为代替, 但String.intern()的缺陷是 如果字符串特别多,导致放入字符串池的String不可控,有可能导致OOM错误或者过多的Full GC 具体参考这里 http://stackoverflow.com/questions/10578984/what-is-string-interning/10579062#10579062 因此使用guava的Inter

c# 中Intern的作用

1. 函数如下 public static string Intern(string str) { if(str == null) { throw new ArgumentNullException("str"); } return Thread.GetDomain().GetOrInterString(str); } 2. 举例说明 string s1 = "name"; string s2 = "name"; 上述函数的作用就是确保s1,s2

【Java必修课】String.intern()原来还能这么用(原理与应用)

1 简介 String.intern()是JDK一早就提供的native方法,不由Java实现,而是底层JVM实现,这让我们对它的窥探提高了难度.特别是在Oracle收购了Sun公司后,源代码不开源了,更无法深入研究了.但我们还是有必要尽量地去探索. 本文将主要讲解一下String.intern()方法的原理.特点,并介绍一个新奇的应用. 2 String的池化 方法intern()的作用就是将String池化,这个池是String的常量池.不同版本的JDK有不同的实现. 2.1 不同实现与不同