java : String 与常量池

来源:互联网 发布:发那科机器人示教编程 编辑:程序博客网 时间:2024/06/06 00:59

先上题目:

        String s1 = "abc";        String s2 = "abc";        System.out.println("s1==s2:"+(s1==s2));//true ,因为指向的是常量池中同一对象。        System.out.println("s1.equals(s2):"+(s1.equals(s2)));//true        String s3 = "ab"+"c";        System.out.println("s1==s3"+(s1==s3));//true,java自动优化为abc字符串 String s3 = "abc";         String s4 = "ab";        /*这里使用的是StringBudiler类的append方法,最后返回的是一个新的String对象         s5 = s4+"c";//这是变量和常量的加法,涉及到Builder         StringBuilder sb = new StringBudiler(s4);         sb.append("c");         s5 = sb.toString(){            return new String(value,0,count);         }        */        String s5 = s4+"c";        System.out.println("s1==s5:"+(s1==s5));//false        System.out.println("s1.equals(s5):"+s1.equals(s5));//false        System.out.println("s1.intern()==s5.intern():"+(s1.intern()==s5.intern()));//true, intern()方法是在常量池中寻找相同的变量。        final String s6 = "ab";        s5 = s6+"c";        System.out.println("s1==s5:"+(s1==s5));//true,final是一个常量,这是常量之间的拼接,不涉及到StringBuilder,        String s7 = "jin|tian|tian|qi|zhen|hao!";        String[] sArray = s7.split("[|]");//这里利用的是spilt()的方法,作用是分割字符串。        for(int i= 0;i<sArray.length;i++){            System.out.println(sArray[i]);        }

知识点:不懂可以看这个。

Java中字符串对象创建有两种形式,一种为字面量形式,如String str = “droid”;,另一种就是使用new这种标准的构造对象的方法,如String str = new String(“droid”);,这两种方式我们在代码编写时都经常使用,尤其是字面量的方式。然而这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池。

工作原理
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。
举例说明
字面量创建形式

String str1 = "droid";

JVM检测这个字面量,这里我们认为没有内容为droid的对象存在。JVM通过字符串常量池查找不到内容为droid的字符串对象存在,那么会创建这个字符串对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量str1。
如果接下来有这样一段代码

String str2 = "droid";

同样JVM还是要检测这个字面量,JVM通过查找字符串常量池,发现内容为”droid”字符串对象存在,于是将已经存在的字符串对象的引用返回给变量str2。注意这里不会重新创建新的字符串对象。
验证是否为str1和str2是否指向同一对象,我们可以通过这段代码

System.out.println(str1 == str2);

结果为true。


可以参看这个

http://www.jb51.net/article/59935.htm
http://developer.51cto.com/art/201106/266454.htm

再来一个

说到java中堆、栈和常量池,首先还是看看他们各自存放的数据类型吧!
堆:存放所有new出来的对象;栈:存放基本类型的变量数据和对象的应用,对象(new出来的对象)本身并不存在栈中,而是存放在堆中或者常量池中(字符串常量对象存放在常量池中);常量池:存放基本类型常量和字符串常量。
对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
而对于字符串来说,其对象的引用都是存储在栈中的,如果是编译期已经创建好(即指用双引号定义的)的就存储在常量池中,如果是运行期(new出来的对象)则存储在堆中。对于equals相等的字符串,在常量池中是只有一份的,在堆中则有多份。
举个例子吧!
String str1=”abc”;
String str2=”abc”;
String str3=”abc”;
String str4=new String(“abc”);
String str5=new String(“abc”);

**对于浅蓝色箭头,通过new操作产生一个字符串(“abc”)时,会先去常量池中查找是否有“abc”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此“abc”对象的拷贝对象,所以,对于String str=new String(“abc”),如果常量池中原来没有”abc”则产生两个对象,否则产生一个对象。
而对于基础类型的变量和常量,变量和引用存储在栈中,常量存储在常量池中。例如:**

这里写图片描述
这里写图片描述

对于成员变量和局部变量来说,成员变量是方法外部,类得内部定义的变量。局部变量就是方法或语句块内部定义的变量,注意,局部变量必须初始化。
局部变量(形式参数)的数据存于栈内存中,并且它(局部变量)随方法的消失而消失。

0 0
原创粉丝点击