`
cdwzwd
  • 浏览: 121656 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

【转】常量池 String equals ==

JVM 
阅读更多
1. 首先String不属于8种基本数据类型,String是一个对象。
因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。
2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;
3. 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”的应用;明白了这些也就知道为何得出此结果了。
4. 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。
5. 关于equals()和==:
  这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。
6. 关于String是不可变的
  这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”;
就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的
分享到:
评论

相关推荐

    String a="hello" String b="hello" a==b 返回true的问题分析

    //在java中有一个常量池,当创建String 类型的引用变量给它赋值时,java会到它的常量池中找"hello world"是不是在常量池中已存在。如果已经存在则返回这个常量池中的"hello world"的地址(在java中叫引用)给变量a 。...

    equals问题经典

    我想问stu1的String name="hck",这个"hck"存在常量池中,它和String s=new String("hck")有什么区别! String s1=new String("abc"); String s2=new String("abc"); s1.equals(s2);结果为true Student stu1=new ...

    java String类常量池分析及"equals"和"==”区别详细介绍

    主要介绍了java String类常量池分析及"equals"和"==”区别详细介绍的相关资料,需要的朋友可以参考下

    Java堆、栈和常量池

    1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据...对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份. 如以下代码: Java代码 String s1 =

    java 面对对象编程.pdf.zip

    面向对象基础 面向对象和面向过程的区别 成员变量与局部变量的区别 创建一个对象用什么运算符?对象实体与对象引用有何不同?...字符串常量池的作用了解吗? String s1 = new String("abc");这句话创建了几个

    Java语言程序设计(第3版)第06章-字符串.pptx

    6.1.1 字符串比较 Java语言程序设计(第3版) 不能使用"=="号来比较字符串内容是否相等 比较内容是否相等: boolean equals(String str) boolean equalsIgnoreCase(String str) s1 s2 Hello Hello 字符串常量池 s1 s2...

    String和StringBuilder、StringBuffer的区别1

    //true}补充:String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是

    java深入解析

    107 话题19 钩深索隐——String字符最大长度的探索 111 话题20 追本溯源——追寻String字面常量的“极限” 116 话题21 旧调重弹——再论equals方法与“==”的 区别 122 话题22 顺藤摸瓜——从字面常量到String常量池 ...

    一些常用的String类方法

    文章目录常用String类方法字符串常量池1.charAt方法2.concat方法3.contains方法4.contains方法5.contentEquals(CharSequence cs)方法6.contentEquals(StringBuffer sb)方法7.endwith和startswith方法8.equals...

    leetcode下载-leetcode:leetcode练习

    相关(不可变、安全、常量池...) StringBuilder/StringBuffer 正则表达式 ArrayList 和 LinkedList 对比:数组实现,按下标查找效率高,删除添加效率低; 链表实现,查找效率低,删除添加效率高(重新设置链表头尾) ...

    超级有影响力霸气的Java面试题大全文档

    wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 17、...

    java 面试题 总结

    wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 14、Overload...

    AIC的Java课程1-6章

     [*]了解Java内存机制:栈、堆、常量池等,理解垃圾回收机制。 第3章 面向过程(数组和方法) 4课时  理解如何声明数组、构造数组、初始化数组以及使用数组中的各个元素。  清楚数组作为...

    Java学习笔记-个人整理的

    {3.3}String常量重利用}{70}{section.3.3} {3.4}正则表达式}{71}{section.3.4} {3.5}StringBuffer}{75}{section.3.5} {3.6}StringBuilder}{76}{section.3.6} {3.7}StringBuilder与StringBuffer的缺点}{76}{...

    亮剑.NET深入体验与实战精要2

    2.11 string和StringBuilder有什么区别 106 2.12 Debug版本和Release版本的 区别 108 本章常见技术面试题 111 常见面试技巧之细节决定成败 111 本章小结 112 第3章 ASP.NET开发大杂烩 113 3.1 页面生命周期 114 ...

    亮剑.NET深入体验与实战精要3

    2.11 string和StringBuilder有什么区别 106 2.12 Debug版本和Release版本的 区别 108 本章常见技术面试题 111 常见面试技巧之细节决定成败 111 本章小结 112 第3章 ASP.NET开发大杂烩 113 3.1 页面生命周期 114 ...

Global site tag (gtag.js) - Google Analytics