java解惑之字符之谜(谜题13)

谜题13:动物庄园

来看下面的java程序将会打印什么?

public class AnimalFarm{

public static void main(String[] args){

final String pig = "length: 10";

final String dog = "length: " + pig.length();

System.out.println("Animals are equal: " + pig == dog);

}

}

对该程序进行表面分析后,我们可能会说这个程序打印的是"Animals are equal: true",因为pig和dog都是final和String类型变量,并且它们都被初始化为字符序列"length: 10",也就是说被pig和dog引用的字符串是彼此相等的。但是,==操作符并不测试两个对象是否相等,而是测试两个对象引用是否相同。换句话说,它测试的是这两个对象引用是否正好引用到同一对象上。而在本例中,它们并非引用到同一对象上。

我们应该都清楚String类型的编译器常量是内存限定的。任何两个String类型的常量表达式,如果指定的是相同的字符序列,那么它们就用同一对象引用来表示。但在上面的示例程序中,pig是用常量表达式初始化的,而dog并不是用常量表达式初始化的。既然语言已经对在常量表达式中允许出现的操作作出了限制,而方法调用又不在其中,那么,这个程序就应该打印Animal are equal: false,但实际上还是不对。运行程序后得到的结果是仅仅打印了false,并没有打印其它任何东西。在谜题11中提到过+操作符,不论是用作加法还是字符串连接操作,它都比==操作符的优先级高,因此println方法的参数是按照下面的方式计算的:

System.out.println(("Animals are equal: " + pig) == dog);

所以这个布尔表达式的值当然是false。所以我们在使用字符串连接操作符时,总是将不平凡的操作数用括号括起来。也就是说,当你不确定是否需要括号时,应当选择稳妥的做法,为它们添加一对括号。例如示例程序:

System.out.println("Animals are equal: " + (pig == dog));

即使我们将程序修改成了这样,该程序仍然是有问题的。如果可以的话,我们所写的代码应该很少依赖于字符串常量的内存限定机制。内存限定机制只是设计用来减少虚拟机内存占有量,并不是程序员的一种工具。就如该谜题所示,哪一个表达式会产生字符串常量并非总是显而易见的。如果你的代码依赖于内存限定机制实现操作的正确性,那么你就必须仔细地了解哪些域和参数必须是内存限定的。编译器不会帮你检查这些变量,因为内存限定的和不限定的字符串使用相同的类型(String)来表示。在内存中限定字符串失败而导致的bug是很难以探测的。

从示例程序中,我们还应该注意的是在比较对象引用时,应该优先使用equal方法而不是==操作符,除非需要比较的是对象的标识而不是对象的值。所以我们修正后的println语句应当是:

System.out.println("Animals are equal: " + pig.equal(dog));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值