java-String中intern()的详解

  这里首先介绍字符串池。类java.lang.String负责维护一个字符串池。可以将字符串池看作一个字符串的集合。在该字符串池中,具有相同字符序列的字符串只对应一个字符串实例对象。该字符串存放3类元素:

  1. 存放字符串常量

  2. 存放有限个字符串直接量进行“+”运算的结果

  3. 由类java.lang.String的成员方法intern创建的字符串实例对象  

  类java.lang.String的成员方法 public String intern() 首先判断当前字符串是否已经在字符串池中。

  • 如果当前字符串已经在字符串池中,则返回当前字符串的引用。

  • 如果当前字符串不再字符串池中而且字符串池已经含有与当前字符串相同字符次序列的字符串实例对象,则返回在字符串池中这个字符串的引用。

  • 如果字符串池中不存在与当前字符串相同字符序列的字符串实例对象,则在字符串池中创建一个相同的字符串实例

  用一句话归纳:对String用intern()后,在字符串池中返回一个相同值的字符串引用(在字符串池中有相同的字符串则直接返回引用,没有则创建一个再返回它的引用)

  再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个
方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,
如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用,看例1就清楚了

String s0=
“kvill”; 
String s1=new
String(”kvill”); 
String s2=new
String(“kvill”); 
System.out.println(
s0==s1 ); 
System.out.println(
“**********”
); 
s1.intern(); 
s2=s2.intern();
//把常量池中“kvill”的引用赋给s2 
System.out.println(
s0==s1); 
System.out.println( s0==s1.intern()
); 
System.out.println( s0==s2
); 
结果为: 

false 
********** 
false
//虽然执行了s1.intern(),但它的返回值没有赋给s1 
true
//说明s1.intern()返回的是常量池中”kvill”的引用 
true 
最后我再破除一个错误的理解: 

有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字
符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的
String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的: 

看例2: 

String
s1=new String("kvill"); 
String
s2=s1.intern(); 
System.out.println( s1==s1.intern()
); 
System.out.println( s1+" "+s2 ); 
System.out.println(
s2==s1.intern() ); 
结果: 

false 
kvill
kvill 
true 
在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加
了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。

最后用一个例子概括:

public static void main(String args[])

{

  String s1 = "123456";  //字符串直接量

  String s2 = "123456";  //字符串直接量

  String s3 = "123"+"456";  //不是字符串直接量

  String a0 = "123";

  String s4 = a0 +"456";  //不是字符串直接量

  String s5 = new
String("123456");  //不是字符串直接量

  String s6 = s5.intern();

  System.out.println("s2"+((s2==s1) ? "==" :
"!=")+"s1");

  System.out.println("s3"+((s3==s1) ? "==" :
"!=")+"s1");

  System.out.println("s4"+((s4==s1) ? "==" :
"!=")+"s1");

  System.out.println("s5"+((s5==s1) ? "==" :
"!=")+"s1");

  System.out.println("s6"+((s6==s1) ? "==" :
"!=")+"s1");

}

运行结果为:

s2 == s1;

s3 == s2;

s4!=s1;

s5!=s1;

s6==s1;

参考链接:http://blog.sina.com.cn/s/blog_69dcd5ed0101171h.html

时间: 2024-10-08 14:46:44

java-String中intern()的详解的相关文章

关于JAVA项目中CLASSPATH路径详解

自己看完总结:配置中"classpath: " 相当于输出目录,即编译后的class文件 所在目录:而 "file:" 是 启动目录而言,14 上服务器就是WEB-INF 下目录,本地项目就是项目根目录. 关于JAVA项目中CLASSPATH路径详解 分类: Java 2013-03-14 10:52 6845人阅读 评论(1) 收藏 举报 在dos下编译java程序,就要用到classpath这个概念,尤其是在没有设置环境变量的时候.classpath就是存放.c

String的Intern方法详解

引言 在 JAVA 语言中有8中基本类型和一种比较特殊的类型String.这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念.常量池就类似一个JAVA系统级别提供的缓存.8种基本类型的常量池都是系统协调的,String类型的常量池比较特殊.它的主要使用方法有两种: 直接使用双引号声明出来的String对象会直接存储在常量池中. 如果不是用双引号声明的String对象,可以使用String提供的intern方法.intern 方法会从字符串常量池中查询当前字符串是否存在,

java String 中 intern方法的概念

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

Java NIO中的Buffer 详解

Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. Buffer的基本用法使用Buffer读写数据一般遵循以下四个步骤: 写入数据到Buffer    调用flip()方法    从Buffer中读取数据    调用clear()方法或者compact()方法 当向buffer写入数据时,

Java web中WEB-INF目录详解

1.它是java的web应用的安全目录.所谓安全就是客户端无法访问,只有服务端可以访问的目录. 2.web.xml项目部署文件. 3.classes文件夹,用以防止*.class文件 4.lib文件夹,用于存放需要的jar包. WEB-INF中配置web.xml文件,添加<welcome-file-list> <welcome-file> 设定的首页文件名 <welcome-file> <welcome-fiel-list>

Java多线程中join方法详解

join()方法用于让当前执行线程等待join线程执行结束.其实现原理是不停的检查join线程是否存活,如果join线程存活则让当前线程永远等待. join()方法部分实现细节 while(isAlive()) { wait(0) } 其中wait(0)表示永远等待下去. join线程中止后,线程的this.notifyAll()方法会被调用,调用notifyAll()是在JVM里调用的所有在JDK中看不到,大家可以看JVM源码 示例程序: public calss ThreadTest{ pu

《Java项目中classpath路径详解》

项目里用到了classpath路径来引用文件,那么classpath指的是哪里呢 我首先把上面的applicationContext.xml文件放在了src目录下发现可以. 那么classpath到底是哪里呢,在网上看了几篇博客 画黄线部分解释了我放在src目录下能用classpath:访问的问题. 但是红线部分,他说这句话对,我感觉有问题. 然后我就试了一下 发现无论是放在WEB-INF目录下,还是WEB-INF/lib下都不行.WEB-INF/classes文件还没有..... 然后去项目W

java中static作用详解

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享. 只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们.因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象. 用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类

Java中的HashTable详解

Hashtables提供了一个很有用的方法可以使应用程序的性能达到最佳. Hashtables(哈 希表)在计算机领域中已不 是一个新概念了.它们是用来加快计算机的处理速度的,用当今的标准来处理,速度非常慢,而它们可以让你在查询许多数据条目时,很快地找到一个特殊的条目. 尽管现代的机器速度已快了几千倍,但是为了得到应用程序的最佳性能,hashtables仍然是个很有用的方法. 设想一下,你有一个 包含约一千条记录的数据文件??比如一个小企业的客户记录还有一个程序,它把记录读到内存中进行处理.每个