首页 > 代码库 > 【java解惑】java字符串比较那些事儿

【java解惑】java字符串比较那些事儿


    如下代码:

public class Example013 {

	public static void main(String[] args) {
		final String pig = "length:8";
		final String pig1 = "length:8";
		int length = pig.length();
		final String dog = "length:" + pig.length();
		System.out.println("pig‘s length is :" + length);
		System.out.println("pig is same as dog ? " + pig == dog); //输出1
		System.out.println("pig is same as pig1 ? " + (pig == pig1));//输出2
		System.out.println("pig is same as dog ? " + (pig == dog));// 输出3
		System.out.println("pig is same as dog ? " + (pig.equals(dog)));// 输出4
	}
}


    输出结果:

pig‘s length is :8
false
pig is same as pig1 ? true
pig is same as dog ? false
pig is same as dog ? true

    

    结果分析:

    了解equals和==区别的小伙伴儿可能会觉得今天这个话题很简单,不了解的小伙伴儿们赶快去恶补吧。一言以蔽之,equals的比较比==更严格,两个对象如果==,一定equals,但是两个对象equals,可不一定==。你可能知道 String 类型的编译期常量是内存限定的。换句话说,任何两个 String类型的常量表达式,如果标明的是相同的字符序列,那么它们就用相同的对象引用来表示。所以输出2打印true也就见怪不怪了。再看输出3,打印的却是false。这里就告诉我们:

    如果可以的话,你的代码不应该依赖于字符串常量的内存限定机制。内存限定机制只是设计用来减少虚拟机内存占有量的,它并不是作为程序员可以使用的一种工具而设计的。

    更糟的是,如果你的代码依赖于内存限定机制实现操作的正确性,那么你就必须仔细地了解哪些域和参数必定是内存限定的。编译器不会帮你去检查这些不变量,因为内存限定的和不限定的字符串使用相同的类型(String)来表示的。这些因在内存中限定字符串失败而导致的 bug 是非常难以探测到的。

    所以,在使用字符串比较时,最好是使用equals方法,如输出4那样,这样得到的结果可以保证是可控、准确的。


    分析完输出2、3、4后,再来看看输出1,它的输出只是一个单纯的false,并没有前导的“pig is same as dog”。这是为什么呢?原因是+的优先级要高于==,所以这里实际执行的代码如下所示:

System.out.println(("pig is same as dog ? " + pig) == dog);

    毫无悬念的,结果当然为false了。



(注:本【java解惑】系列,均是博主阅读《java解惑》原书后,将原书上的讲解和例子部分改编,然后写成博文进行发布的。所有例子均亲自测试通过,并共享在github上。通过这些例子,激励自己,惠及他人。同时,本系列所有博文会同步发布在博主个人微信公众号(搜索“爱题猿”或者“ape_it”),方便大家阅读。如果文中有任何侵犯原作者权利的内容,请及时告知博主,以便及时删除;如果读者对文中的内容有异议或者问题,欢迎通过博客留言或者微信公众号留言等方式共同探讨。)

源代码地址:https://github.com/rocwinger/java-disabuse


本文出自 “winger” 博客,谢绝转载!

【java解惑】java字符串比较那些事儿