String a ="abc" String b="abc" String c=new String("abc"); String d="ab"+"c"之间用==比较的结果

做个string的测试咯。如下:


/**

[java]  view plain  copy
  1.  * Created by lxk on 2016/8/19  
  2.  */  
  3. public class Test {  
  4.     public static void main(String[] args) {  
  5.         String a = "abc";  
  6.         String b = "abc";  
  7.         String c = new String("abc");  
  8.         String d = "ab" + "c";  
  9.         System.out.println("a == b" + a == b); //false   
  10.         System.out.println("a == c" + a == c); //false   
  11.         System.out.println("a == d" + a == d); //false   
  12.         System.out.println("b == c" + b == c); //false   
  13.         System.out.println("b == d" + b == d); //false   
  14.         System.out.println("c == d" + c == d); //false   
  15.     }  
  16. }  

代码中警告的原因:
(1)
String c = new String("abc");
可以直接写成如下,上面那么写,就有些啰嗦,脱裤子放屁。哎呀,好不优雅的比喻。咦。。。
String c = "abc";
(2)
意思就是字符串比较不能用  == ,要用equals()方法

注意:

上面的代码和测试结果,都是完全错误的,一失足成千古恨。

要是你一眼就能看到我哪里错了,说明你很还是很牛x的。没一眼看出来,也不要紧。

下面再进行正确的测试。并说明上面错误的地方。

下面是正确的测试代码和测试结果。



测试代码:

[java]  view plain  copy
  1. package com.lxk.test;  
  2.   
  3. /** 
  4.  * 字符串测试Class 
  5.  * <p> 
  6.  * Created by lxk on 2017/2/8 
  7.  */  
  8. public class StringTest {  
  9.     public static void main(String[] args) {  
  10.         testStringPool();  
  11.     }  
  12.   
  13.     /** 
  14.      * 测试字符串常量池的问题 
  15.      */  
  16.     private static void testStringPool() {  
  17.         String a = "abc";//字面量形式  
  18.         String b = "abc";//字面量形式  
  19.         String c = new String("abc");//使用new标准的构造对象  
  20.         /* 
  21.             注意:这个虽然看起来似乎要在常量池新建三个字符串对象:ab,c,和拼接生成的abc 
  22.             但是结果是内存中仅有生成的,前面的两个算是过程变量。这反编译得出来的结论,我没测试哟! 
  23.             这样做实际上是一种优化,避免了创建多余的字符串对象,也没有发生字符串拼接问题 
  24.          */  
  25.         String d = "ab" + "c";//字面量形式  
  26.         System.out.println("a == b " + (a == b));//true  
  27.         System.out.println("a == c " + (a == c));//false  
  28.         System.out.println("a == d " + (a == d));//true  
  29.         System.out.println("b == c " + (b == c));//false  
  30.         System.out.println("b == d " + (b == d));//true  
  31.         System.out.println("c == d " + (c == d));//false  
  32.         System.out.println("-----------------");  
  33.         System.out.println("abc" == ("ab" + "c"));//true  
  34.         System.out.println("-----------------");  
  35.         String e = c.intern();//将new出来的字符串对象加入字符串常量池  
  36.         System.out.println(a == e);//true  
  37.     }  
  38. }  


对上面结果的解释说明:
首先上面的比较过程是直接拿 == 来比较的,没有用equal方法,那么用 == 来比较的话,比较的是地址。并不是值
可以看到,a,b,d,三个字符串直接用 == 比较,比较出来的结果都是true。是相等的。
意思就是说这三个变量在空间上都是指向同一个内存地址。这就涉及到一个字符串常量池的问题啦。
但是和c比较的时候,却不相等,因为,c是new出来的,记得当时学习的时候,new都是在堆内存里面的,新开辟的空间。
所以,地址肯定就不相同啦。


对上面的错误测试做解释:

我之所以错误了 ,是因为,我在打印结果的时候,没有注意到运算符的优先级问题。

我也没有看到我的打印结果和自己期望的结果是不同的,期望结果起码应该是:a == b false,这个形式的,但是我却没有注意到我当时代码的测试结果仅仅只有:false。

知道问题所在的话,就知道上面的代码怎么错了:前面的字符先是拼接起来,然后再和后面的变量字符串对比,结果当然是false啦。

所以,之前的测试结果一直都是false。

尴尬啦。


之所以有这篇文章,估计当时,看到这个问题,在网上搜索,答案五花八门。所以,我就自己亲自动手,搞了个测试。万万没想到。我还给搞错了。多谢下面那位仁兄的评论,我又回头 再看这个问题,就发现问题所在啦。


关于常量池的简单解释:(后面追加的内容)

Java中字符串对象创建有两种形式。
一种为字面量形式,如String str = "droid";,
另一种就是使用new这种标准的构造对象的方法,如String str = new String("droid");
这两种方式我们在代码编写时都经常使用,尤其是字面量的方式。然而这两种实现其实存在着一些性能和内存占用的差别。
这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池。
工作原理
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查。
如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回。
否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。


经过上面的这番解释,可以知道,新添加的那行代码的运行结果应该是:true。


以下是更新于(2017/06/23)


就算你仔细看了上面的测试代码,要是再这么一下,稍微加个final,修饰一下字符串。那么结果又有点不同啦。

具体运行结果,如下图。


对上述运行结果的解释:

这里面就是final变量和普通变量的区别了.
当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。
也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。
这种和C语言中的宏替换有点像。
因此在上面的一段代码中,由于变量bb被final修饰,因此会被当做编译器常量,所以在使用到bb的地方会直接将变量bb替换为它的值。
而对于变量dd的访问却需要在运行时通过链接来进行。
想必其中的区别大家应该明白了.
不过要注意,只有在编译期间能确切知道final变量值的情况下.编译器才会进行这样的优化.


为什么有这次更新

因为在看到final的用法的时候,又出现了字符串比较,又涉及到了字符串常量池的问题,我就干脆放一起好啦

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值