天猫|Java虚拟机堆和栈详细解析,以后面试再也不怕问JVM(文末福利)( 四 )


示例:
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 表理解为常量池的话 , 他的最后一句话 , ”如果在表中没有相同值的字符串 , 则将自己的地址注册到表中”是错的:
示例:
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;而==是 比较两字符串的地址是否相同 , 也就是是否是同一个字符串的引用 。
【天猫|Java虚拟机堆和栈详细解析,以后面试再也不怕问JVM(文末福利)】6. 关于String是不可变的
这一说又要说很多 , 大家只 要知道String的实例一旦生成就不会再改变了 , 比如说:String str=”kv”+”ill”+” “+”ans”; 就是有4个字符串常量 , 首先”kv”和”ill”生成了”kvill”存在内存中 , 然后”kvill”又和” ” 生成 “kvill “存在内存中 , 最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str就是因为String的”不可变”产生了很多临时变量 , 这也就是为什么建议用StringBuffer的原 因了 , 因为StringBuffer是可改变的 。
下面是一些String相关的常见问题:
String中的final用法和理解
final StringBuffer a = new StringBuffer(\"111\"); final StringBuffer b = new StringBuffer(\"222\"); a=b;//此句编译不通过 final StringBuffer a = new StringBuffer(\"111\"); a.append(\"222\");// 编译通过
可见 , final只对引用的\"值\"(即内存地址)有效 , 它迫使引用只能指向初始指向的那个对象 , 改变它的指向会导致编译期错误 。 至于它所指向的对象 的变化 , final是不负责的 。
String常量池问题的几个例子
下面是几个常见例子的比较分析和理解:
String a = \"a1\";  

String b = \"a\" + 1;  

System.out.println((a == b)); //result = true  

String a = \"atrue\";  

String b = \"a\" + \"true\";  

System.out.println((a == b)); //result = true  

String a = \"a3.4\";  

String b = \"a\" + 3.4;  

System.out.println((a == b)); //result = true