java String 中 intern方法的理解

原创 2016年08月28日 16:46:23
  1. String基本概念

    首先String不属于8种基本数据类型,String是一个对象。
    因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

  2. 创建String的不同

    new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;

  3. String作为常量引用

    String str=”kvill”;
    String str=new String (“kvill”);的区别:

    在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。

    常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

    看例1:

String 
s0=”kvill”; 
String 
s1=”kvill”; 
String 
s2=”kv” + “ill”; 
System.out.println( 
s0==s1 ); 
System.out.println( 
s0==s2 ); 

结果为: true true
首先,我们要知道Java会确保一个字符串常量只有一个拷贝。

因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中
”kvill”的一个引用。

所以我们得出s0==s1==s2;

用new
String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

看例2:

String 
s0=”kvill”; 
String 
s1=new String(”kvill”); 
String 
s2=”kv” + new String(“ill”); 
System.out.println( 
s0==s1 ); 
System.out.println( 
s0==s2 ); 
System.out.println( 
s1==s2 ); 

结果为:

false
false
false
例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分new
String(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。

  1. String.intern():

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

例3:

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表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:

看例4:

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”仍然存在,也就不是“将自己的地址注册到常量池中”了。

s1==s1.intern()为false说明原来的“kvill”仍然存在;

s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。


  1. 关于equals()和==:

这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。


  1. 关于String是不可变的

这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String
str=”kv”+”ill”+” “+”ans”;
就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和”
“ 生成 ”kvill “存在内存中,最后又和生成了”kvill
ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java技术——你真的了解String类的intern()方法吗

说实话我本来想总结一篇Android内存泄漏的文章的,查阅了很多资料,发现不得不从Java的OOM讲起,讲Java的OOM又不得不讲Java的虚拟机架构。在JVM架构一文中也有介绍,在JVM运行时数据...
  • SEU_Calvin
  • SEU_Calvin
  • 2016年08月23日 16:40
  • 27649

Java技术——你真的了解String类的intern()方法吗

0.引言 什么都先不说,先看下面这个引入的例子: [java] view plain copy String str1 = new String("SEU")+ new Stri...
  • baidu_31657889
  • baidu_31657889
  • 2016年08月25日 16:30
  • 8619

深入理解java虚拟机(三):String.intern()-字符串常量池

深入理解java虚拟机(一):java内存区域(内存结构划分) 深入理解java虚拟机(二):java内存溢出实战   看源码:  public native String intern();    ...
  • MINEZHANGHAO
  • MINEZHANGHAO
  • 2014年02月19日 14:47
  • 11340

java6,7,8中String.intern进化史与深度剖析

这篇文章将要讨论 Java 6 中是如何实现 String.intern 方法的,以及这个方法在 Java 7 以及 Java 8 中做了哪些调整。 字符串池 字符串池(有名字符串标准化)是通过使用唯...
  • chenleixing
  • chenleixing
  • 2015年05月14日 08:48
  • 1895

String中intern的方法

String中intern的方法 首先查看官方API那个的解释: ——————————————————————————————————————— intern public S...
  • yaerfeng
  • yaerfeng
  • 2013年07月01日 14:09
  • 1186

关于java String的intern()方法的理解

1.首先先来看这样一个问题: String s1 = new String (“test”); String s2 = new String(“test”); 在这个过程中,创建了几个Strin...
  • weizi2016
  • weizi2016
  • 2017年02月15日 19:37
  • 90

java中String的intern()方法理解

1. 首先String不属于8种基本数据类型,String是一个对象。因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。 2. ne...
  • renyp8799
  • renyp8799
  • 2015年05月27日 17:10
  • 301

java代码性能提高技巧之String.intern()

这篇文章将要讨论 Java 6 中是如何实现 String.intern 方法的,以及这个方法在 Java 7 以及 Java 8 中做了哪些调整。 字符串池      字符串池(有名字符串标...
  • zhushuai1221
  • zhushuai1221
  • 2016年09月25日 20:00
  • 427

几张图轻松理解String.intern()

在翻《深入理解Java虚拟机》的书时,又看到了2-7的 String.intern()返回引用的测试。 其实要搞明白String.intern(),我总结了下面几条规则: 一、new String...
  • soonfly
  • soonfly
  • 2017年04月12日 20:35
  • 979

深入理解String和intern方法

定义字符串:String str=”abc”;  和String str=new String(“abc”); 的区别: String str="abc"; String str1=n...
  • u012813201
  • u012813201
  • 2017年06月23日 11:12
  • 113
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java String 中 intern方法的理解
举报原因:
原因补充:

(最多只允许输入30个字)