您现在的位置: 中国男护士网 >> 考试频道 >> 计算机等级 >> 二级辅导 >> JAVA >> 辅导 >> 正文    
  JAVA字符谜题3:畜牧场 【注册男护士专用博客】          

JAVA字符谜题3:畜牧场

www.nanhushi.com     佚名   不详 

  George Orwell的《畜牧场(Animal Farm)》一书的读者可能还记得老上校的宣言:“所有的动物都是平等的。”下面的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);
    }
}

    对该程序的表面分析可能会认为它应该打印出Animal are equal: true。毕竟,pig和dog都是final的string类型变量,它们都被初始化为字符序列“length: 10”。换句话说,被pig和dog引用的字符串是且永远是彼此相等的。然而,==操作符测试的是这两个对象引用是否正好引用到了相同的对象上。在本例中,它们并非引用到了相同的对象上。 
你可能知道String类型的编译期常量是内存限定的。换句话说,任何两个String类型的常量表达式,如果标明的是相同的字符序列,那么它们就用相同的对象引用来表示。如果用常量表达式来初始化pig和dog,那么它们确实会指向相同的对象,但是dog并不是用常量表达式初始化的。既然语言已经对在常量表达式中允许出现的操作作出了限制,而方法调用又不在其中,那么,这个程序就应该打印Animal are equal: false,对吗? 
嗯,实际上不对。如果你运行该程序,你就会发现它打印的只是false,并没有其它的任何东西。它没有打印Animal are equal: 。它怎么会不打印这个字符串字面常量呢?毕竟打印它才是正确的呀!谜题11的解谜方案包含了一条暗示:+ 操作符,不论是用作加法还是字符串连接操作,它都比 == 操作符的优先级高。因此,println方法的参数是按照下面的方式计算的: 
System.out.println(("Animals are equal: " + pig) == dog);

    这个布尔表达式的值当然是false,它正是该程序的所打印的输出。 
有一个肯定能够避免此类窘境的方法:在使用字符串连接操作符时,总是将非平凡的操作数用括号括起来。更一般地讲,当你不能确定你是否需要括号时,应该选择稳妥地做法,将它们括起来。如果你在println语句中像下面这样把比较部分括起来,它将产生所期望的输出Animals are equal: false : 
System.out.println("Animals are equal: " + (pig == dog));

   可以论证,该程序仍然有问题。 
如果可以的话,你的代码不应该依赖于字符串常量的内存限定机制。内存限定机制只是设计用来减少虚拟机内存占有量的,它并不是作为程序员可以使用的一种工具而设计的。就像这个谜题所展示的,哪一个表达式会产生字符串常量并非总是很显而易见。 
更糟的是,如果你的代码依赖于内存限定机制实现操作的正确性,那么你就必须仔细地了解哪些域和参数必定是内存限定的。编译器不会帮你去检查这些不变量,因为内存限定的和不限定的字符串使用相同的类型(String)来表示的。这些因在内存中限定字符串失败而导致的bug是非常难以探测到的。 
在比较对象引用时,你应该优先使用equals方法而不是 == 操作符,除非你需要比较的是对象的标识而不是对象的值。通过把这个教训应用到我们的程序中,我们给出了下面的println语句,这才是它应该具有的模样。很明显,在用这种方式订正了该程序之后,它将打印出true: 
System.out.println("Animals are equal: " + pig.equals(dog));

   这个谜题对语言设计者来说有两个教训。 
字符串连接的优先级不应该和加法一样。这意味着重载 + 操作符来执行字符串连接是有问题的,就像在谜题11中提到的一样。 
还有就是,对于不可修改的类型,例如String,其引用的等价性比值的等价性更加让人感到迷惑。也许 == 操作符在被应用于不可修改的类型时应该执行值比较。要实现这一点,一种方法是将 == 操作符作为equals方法的简便写法,并提供一个单独的类似于System.identityHashCode的方法来执行引用标识的比较。 

 

文章录入:杜斌    责任编辑:杜斌 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
     

    联 系 信 息
    QQ:88236621
    电话:15853773350
    E-Mail:malenurse@163.com
    免费发布招聘信息
    做中国最专业男护士门户网站
    最 新 热 门
    最 新 推 荐
    相 关 文 章
    没有相关文章
    专 题 栏 目

      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)                            【进男护士社区逛逛】
    姓 名:
    * 游客填写  ·注册用户 ·忘记密码
    主 页:

    评 分:
    1分 2分 3分 4分 5分
    评论内容:
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。