常量池字符串解析

网上关于String和文章太多了,很多一知半解的作者都在误导大众,本人也是深受其害啊,直到今天看了这篇文章(http://www.wtoutiao.com/a/1023451.html),才拨开层层迷雾,发现JDK6和7的实现还不一样呢,发帖纪录一下。

1 一定要注意String s1=new String("c");
2 这句话的意思是,编译期在常量池就生成了字符串"c",。运行时在堆也生成了一个string对象"c",注意这两个字符串没有丝毫的关系。当执行s1.intern()时,编译器去常量池查找,发现常量池已经存在了字符串"c",所以什么都不干。这句话不会导致任何结果。可是如果是 String s2=s1.intern();s2会直接指向常量池中的这个字符串。
3 只要是有new关键字即new String("c");都会在堆里面生成一个新的"c",这个"c"个和常量池没有关系。 
1 如果常量池中本来就有这个字符串,则调用intern方法,不会有任何后果,相当于没调用。
2 只有当常量池中不含有这个字符串的时候,调用intern方法才会导致常量池和堆产生关系,即在常量池中新建一个“字符串常量”,确切的说这个“字符串常量”不是字符串,只是指向字符串的引用,真正的字符串在堆里面。
1 重要的内容再次强调一下:
2 s.intern()方法作用:如果常量池中存在字符串s , 就会直接返回 字符串 s 在常量池中的地址, 如果常量池中没有字符串s , 会将 堆中的字符串s 的地址放入常量池中, 然后返回的是堆中字符串s 的地址,这种情况下,常量池中存储的其实不是真正的字符串,而是指向堆中真正字符串的引用。
 1 看下面的代码: (编译器在常量池已经生成了三个字符串,分别是a、b、ab,下面详细分析运行时在对中新创建的字符串对象)
 2         String s1=new String("a")+new String("b");
 3 //两个new分别在对中产生a、b两个字符串,加号导致的结果是产生一个StringBuffer,
 4 初始内容是a,append(b),然后调用toString方法,产生String对象"ab"
 5         String s2=s1.intern();
 6 //检查常量池,因为常量池中不存咋字符串"ab",所以把把堆中的字符串"ab"的引用放入常量池,
 7 注意常量池中存储的不是真实的string对象,而是一个引用,真正的string对象在堆中。
 8         String s3=new String("a")+new String("b");//s1同理
 9         String s4=s3.intern();//核心就是这里,s4其实指向的是s1,理解了这里就算是真正理解了jdk7的常量池了。(区别于jdk6)
10
11         System.out.println(s2==s1);
12         System.out.println(s4==s3);
13         System.out.println(s4==s2);
14 结果:
15 true
16 false
17 true  

最后还是要说一句,网上各路大神都自视对java的虚拟机、常量池很了解,其实都是在误人误己,特别是这篇文章(http://www.iteye.com/topic/522167),现在才发现在堆里面根本没有什么所谓的“拘留字符串区”。

以上是我的一些理解,如果有什么错误,欢迎同行批评指正。

时间: 2024-12-24 06:17:09

常量池字符串解析的相关文章

小数据池 (常量池 -> 字符串缓存) is和==的区别 重新看编码 以及编码之间相互转化

?. 小数据池 在说小数据池之前. 我们先看一个概念念. 什么是代码块: 根据提示我们从官?方?文档找到了这样的说法: A Python program is constructed from code blocks. A block is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class defin

Java常量池解析与字符串intern简介

在Java应用程序运行时,Java虚拟机会保存一份内部的运行时常量池,它区别于class文件的常量池,是class文件常量池映射到虚拟机中的数据结构. 1.CONSTANT_Class入口解析 数组类的符号解析较为特殊.若是基本类型数组,那么虚拟机将创建该基本类型的新数组类,并创建一个Class实例来代表该类型,数组类的定义类加载器为 启动类加载器.若是引用类型的数组,那么在此之前还会进行引用类型的解析,数组类的定义类加载器为引用类型的定义类加载器. 非数组类和接口的的解析将经历以下步骤: (1

什么是字符串常量池?

什么是字符串常量池? 在理解字符串常量前,我们先熟悉一下如何创建一个字符串,在Java中有两种方法可以创建一个字符串对象: 使用new运算符.例如: 1 String str = new String("Hello"); 使用字符串常量或者常量表达式.例如: 1 2 String str="Hello"; //(字符串常量) 或者 String str="Hel" + "lo"; //(字符串常量表达式). 这些字符串的创建方

【基础】Java 8 中的常量池、字符串池、包装类对象池

1 - 引言 2 - 常量池 2.1 你真的懂 Java的“字面量”和“常量”吗? 2.2 常量和静态/运行时常量池有什么关系?什么是常量池? 2.3 字节码下的常量池以及常量池的加载机制 2.4 是不是所有的数字字面量都会被存到常量池中?3 - 包装类对象池 $\ne$JVM 常量池4 - 字符串池 4.1 字符串池的实现——StringTable 4.2 字符串池存的是实例还是引用?5 - 补充 5.1 永久代为何被 HotSpot VM 废弃? 5.2 为什么 Java 要分常量.简单类型

Java中的字符串常量池

最近做到一个题目: 问题:String str = new String("abc"),"abc"在内存中是怎么分配的?    答案是:堆,字符串常量区. 题目考查的为Java中的字符串常量池和JVM运行时数据区的相关概念."abc"为字面量对象,其存储在堆内存中.而字符串常量池则存储的是字符串对象的一个引用. Java中的字符串常量池 Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid&qu

基本数据类型的常量池与String类型常量池解析

抛出样例: Integer a1  = new Integer(123);        Integer a2  = new Integer(123);        System.out.println(a1 == a2);   //false  因为只要遇到new关键词,肯定会在堆里面重新分配空间给实例对象,所以两个地址肯定不同                a1  = 123;        a2  = 123;        System.out.println(a1 == a2); 

转载:Java中的字符串常量池详细介绍

引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池,需要的朋友可以参考下 Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new Stri

彻底弄懂字符串常量池等相关问题

前言: 在平时我们使用字符串一般就是拿来直接搞起,很少有深入的去想过这方面的知识,导致别人在考我们的时候,会问 String str = new String("123"); 这个一行代码执行创建了几个对象, String str1= str + new String("456");这行代码中str1存储在内存的哪个位置,堆or 字符串常量区(方法区)? 会把我们问的哑口无言了:哈哈哈哈,其实也不是水平问题,是我们平时可以仔细的去总结该类问题,下面就详细的对这类问题

java值和地址值传递、字符串常量池的理解

#java值和地址值传递的理解: - 基本数据类型和基本数据类型的封装类都是:值传递 * 形式参数的改变不会影响实际参数的改变(相当于将值复制一份传递给形参,自身没做任何改变) - 引用数据类型都是 地址值传递 * 形式参数的改变会影响实际参数的改变(将地址值赋值给形参,形参就可以指向实参所指向的地址, 即形参也可以操作实参指向地址的数据了) #注意:String是个特例(当作基本类型处理) - 分析:从String类的源码可以知道,String相当于是char[]的封装类,即具有char类型的