java中的String类常量池详解
2013-01-25 17:44
288 查看
原文:http://www.cesclub.com/bw/jishuzhongxin/wangluokaifajishu/2011/0826/5680.html
encodeURI不合错误下列字符进行编码:“:”、“/”、“;”、“?”、“@”等希罕字符。
所有巨大的事迹和巨大的思惟都有荒诞的开首。
从一个博客上看到的6个题,先看看吧,若是都邑了,这项目组的常识就把握的不错啦!输出成果在代码注释后面:
test1:
test2:
test3:
test4:
test5:
test6:
-------------------------------------------------------------------------------------------------------------------------------------------------
String常量池详解:
1.String应用private final char value[]来实现字符串的存储,也就是说String对象创建之后,就不克不及再批改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的(immutable)。String类有一个特别的创建办法,就是应用""双引号来创建.例如new String("i am")实际创建了2个
String对象,一个是"i am"经由过程""双引号创建的,另一个是经由过程new创建的.只不过他们创建的时代不合,
一个是编译期,一个是运行期!java对String类型重载了+操纵符,可以直接应用+对两个字符串进行连接。运行期调用String类的intern()办法可以向String Pool中动态添加对象。
例1
String s1 = "sss111";
//此语句同上
String s2 = "sss111";
System.out.println(s1 == s2); //成果为true
例2
String s1 = new String("sss111");
String s2 = "sss111";
System.out.println(s1 == s2); //成果为false
例3
String s1 = new String("sss111");
s1 = s1.intern();
String s2 = "sss111";
System.out.println(s1 == s2);//成果为true
例4
String s1 = new String("111");
String s2 = "sss111";
String s3 = "sss" + "111";
String s4 = "sss" + s1;
System.out.println(s2 == s3); //true
System.out.println(s2 == s4); //false
System.out.println(s2 == s4.intern()); //true
成果上方解析,总结如下:
1.零丁应用""引号创建的字符串都是常量,编译期就已经断定存储到String Pool中;
2,应用new String("")创建的对象会存储到heap中,是运行期新创建的;
3,应用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能断定,已经断定存储到String Pool中;
4,应用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中;
还有几个经常考的口试题:
String s1 = new String("s1") ;
String s2 = new String("s1") ;
上方创建了几个String对象?
答案:3个 ,编译期Constant Pool中创建1个,运行期heap中创建2个.(用new创建的每new一次就在堆上创建一个对象,用引号创建的若是在常量池中已有就直接指向,不消创建)
String s1 = "s1";
String s2 = s1;
s2 = "s2";
s1指向的对象中的字符串是什么?
答案: "s1"。(永远不要忘了String不成变的,s2 = "s2";实际上s2的指向就变了,因为你不成以去改变一个String,)
--------------------------------------------------------------------------------------------------------------------------------------------------
String是一个特别的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的情势来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后经由过程符号引用去字符串常量池里找有没有"abc",若是没有,则将"abc"存放进字符串常量池,并令str指向”abc”,若是已经有”abc” 则直接令str指向“abc”。
斗劲类里面的数值是否相等时,用equals()办法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子申明上方的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的体式格式是生成不合的对象。每一次生成一个。
因此用第二种体式格式创建多个”abc”字符串,在内存中其实只存在一个对象罢了. 这种写法有利与节俭内存空间. 同时它可以在必然程度上进步法度的运行速度,因为JVM会主动按照栈中数据的实际景象来决意是否有须要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有须要创建新对象,从而加重了法度的肩负。
另一方面, 要重视: 我们在应用诸如String str = "abc";的格局定义类时,老是想当然地认为,创建了String类的对象str。愁闷陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有经由过程new()办法才干包管每次都创建一个新的对象。
因为String类的immutable性质,当String变量须要经常变换其值时,应当推敲应用StringBuffer类,以进步法度效力。
1. 起首String不属于8种根蒂根基数据类型,String是一个对象。
因为对象的默认值是null,所以String的默认值也是null;但它又是一种特别的对象,有其它对象没有的一些特点。
2. new String()和new String(”")都是申明一个新的空字符串,是空串不是null;
3. String str=”kvill”;String str=new String (”kvill”)的差别
看例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。
encodeURI不合错误下列字符进行编码:“:”、“/”、“;”、“?”、“@”等希罕字符。
所有巨大的事迹和巨大的思惟都有荒诞的开首。
从一个博客上看到的6个题,先看看吧,若是都邑了,这项目组的常识就把握的不错啦!输出成果在代码注释后面:
test1:
青年时的失败要比丁壮时的成功,老年时的成功更令人合意。package StringTest; public class test1 { /** * @param args */ public static void main(String[] args){ String a = "a1"; String b = "a"+ 1; System.out.println(a==b); }//true }
test2:
package StringTest; public class test2 { /** * @param args */ public static void main(String[] args){ String a = "ab"; String bb = "b"; String b = "a"+ bb; //编译器不克不及断定为常量 System.out.println(a==b); }//false }
test3:
package StringTest; public class test3 { /** * @param args */ public static void main(String[] args){ String a = "ab"; final String bb = "b"; String b = "a"+ bb; //bb加final后是常量,可以在编译器断定b System.out.println(a==b); }//true }
test4:
package StringTest; public class test4 { /** * @param args */ public static void main(String[] args){ String a = "ab"; final String bb = getBB(); String b = "a"+ bb;//bb是经由过程函数返回的,固然知道它是final的,但不知道具体是啥,要到运行期才知道bb的值 System.out.println(a==b); }//false private static String getBB(){ return "b"; } }
test5:
package StringTest; public class test5 { /** * @param args */ private static String a = "ab"; public static void main(String[] args){ String s1 = "a"; String s2 = "b"; String s = s1 + s2;//+的用法 System.out.println(s == a); System.out.println(s.intern() == a);//intern的含义 }//flase true }
test6:
package StringTest; public class test6 { /** * @param args */ private static String a = new String("ab"); public static void main(String[] args){ String s1 = "a"; String s2 = "b"; String s = s1 + s2; System.out.println(s == a); System.out.println(s.intern() == a); System.out.println(s.intern() == a.intern()); }//flase false true }
-------------------------------------------------------------------------------------------------------------------------------------------------
String常量池详解:
1.String应用private final char value[]来实现字符串的存储,也就是说String对象创建之后,就不克不及再批改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的(immutable)。String类有一个特别的创建办法,就是应用""双引号来创建.例如new String("i am")实际创建了2个
String对象,一个是"i am"经由过程""双引号创建的,另一个是经由过程new创建的.只不过他们创建的时代不合,
一个是编译期,一个是运行期!java对String类型重载了+操纵符,可以直接应用+对两个字符串进行连接。运行期调用String类的intern()办法可以向String Pool中动态添加对象。
例1
String s1 = "sss111";
//此语句同上
String s2 = "sss111";
System.out.println(s1 == s2); //成果为true
例2
String s1 = new String("sss111");
String s2 = "sss111";
System.out.println(s1 == s2); //成果为false
例3
String s1 = new String("sss111");
s1 = s1.intern();
String s2 = "sss111";
System.out.println(s1 == s2);//成果为true
例4
String s1 = new String("111");
String s2 = "sss111";
String s3 = "sss" + "111";
String s4 = "sss" + s1;
System.out.println(s2 == s3); //true
System.out.println(s2 == s4); //false
System.out.println(s2 == s4.intern()); //true
成果上方解析,总结如下:
1.零丁应用""引号创建的字符串都是常量,编译期就已经断定存储到String Pool中;
2,应用new String("")创建的对象会存储到heap中,是运行期新创建的;
3,应用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能断定,已经断定存储到String Pool中;
4,应用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中;
还有几个经常考的口试题:
String s1 = new String("s1") ;
String s2 = new String("s1") ;
上方创建了几个String对象?
答案:3个 ,编译期Constant Pool中创建1个,运行期heap中创建2个.(用new创建的每new一次就在堆上创建一个对象,用引号创建的若是在常量池中已有就直接指向,不消创建)
String s1 = "s1";
String s2 = s1;
s2 = "s2";
s1指向的对象中的字符串是什么?
答案: "s1"。(永远不要忘了String不成变的,s2 = "s2";实际上s2的指向就变了,因为你不成以去改变一个String,)
--------------------------------------------------------------------------------------------------------------------------------------------------
String是一个特别的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的情势来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后经由过程符号引用去字符串常量池里找有没有"abc",若是没有,则将"abc"存放进字符串常量池,并令str指向”abc”,若是已经有”abc” 则直接令str指向“abc”。
斗劲类里面的数值是否相等时,用equals()办法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子申明上方的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的体式格式是生成不合的对象。每一次生成一个。
因此用第二种体式格式创建多个”abc”字符串,在内存中其实只存在一个对象罢了. 这种写法有利与节俭内存空间. 同时它可以在必然程度上进步法度的运行速度,因为JVM会主动按照栈中数据的实际景象来决意是否有须要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有须要创建新对象,从而加重了法度的肩负。
另一方面, 要重视: 我们在应用诸如String str = "abc";的格局定义类时,老是想当然地认为,创建了String类的对象str。愁闷陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有经由过程new()办法才干包管每次都创建一个新的对象。
因为String类的immutable性质,当String变量须要经常变换其值时,应当推敲应用StringBuffer类,以进步法度效力。
1. 起首String不属于8种根蒂根基数据类型,String是一个对象。
因为对象的默认值是null,所以String的默认值也是null;但它又是一种特别的对象,有其它对象没有的一些特点。
2. new String()和new String(”")都是申明一个新的空字符串,是空串不是null;
3. String str=”kvill”;String str=new String (”kvill”)的差别
看例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。
相关文章推荐
- java中的String类常量池详解
- Java中的String类常量池详解
- java中的String类常量池详解
- java中的String类常量池详解
- java中的String类常量池详解-----作者:kkgreen(转)
- java中的String类常量池详解
- java中的String类常量池详解
- java中String类常量池详解
- java中的String类常量池详解
- java中的String类常量池详解
- Java中的String类常量池详解
- java内存分配 常量池详解
- java中String类常量池分析及"equals"和"==”异同
- java中String类详解(享元模式思考)
- Java String类详解
- Java String类中的常量池鱼intern()
- java中String类详解
- Java常用类(二)String类详解
- Java String类详解_动力节点Java学院整理
- Java中堆栈常量池等内存分配原理详解