`
dandy
  • 浏览: 67247 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

对字符串上瘾

    博客分类:
  • java
阅读更多
出自 《java puzzle》

一个名字可以被用来引用位于不同包内的多个类。下面的程序就是在探究当你重用了一个平台类的名字时,会发生什么。你认为它会做些什么呢?尽管这个程序属于那种让你通常一看到就会感到尴尬的程序,但是你还是应该继续下去,把门锁上,把百叶窗拉上,然后试试看:
public class StrungOut {
public static void main(String[] args) {
String s = new String("Hello world");
System.out.println(s);
}
}
class String {
private final java.lang.String s;
public String(java.lang.String s) {
this.s = s;
}
public java.lang.String toString() {
return s;
}
}


如果说这个程序有点让人讨厌的话,它看起来还是相当简单的。在未命名包中的String类就是一个java.lang.String实例的包装器,看起来该程序应该打印Hello world。如果你尝试着运行该程序,你会发现你运行不了它,VM将弹出了一个像下面这样的错误消息:
Exception in thread "main" java.lang.NoSuchMethodError: main
但是它肯定是一个main方法的:它就白纸黑字地写在那里。为什么VM找不到它呢?
VM不能找到main方法是因为它并不在那里。尽管StrungOut有一个被命名为main的方法,但是它却具有错误的签名。一个main方法必须接受一个单一的字符串数组参数[JVMS 5.2]。VM努力要告诉我们的是StrungOut.main接受的是由我们的String类所构成的数组,它无论如何都与java.lang.String没有任何关系。
如果你确实需要编写自己的字符串类,看在老天爷的份上,千万不要称其为String。要避免重用平台类的名字,并且千万不要重用java.lang中的类名,因为这些名字会被各处的程序自动加载。程序员习惯于看到这些名字以无限定的形式出现,并且会很自然地认为这些名字引用的是我们所熟知的java.lang中的类。如果你重用了这些名字的某一个,那么当这个名字在其自己的包内被使用时,该名字的无限定形式将会引用到新的定义上。
要订正该程序,只需为这个非标准的字符串类挑选一个合理的名字即可。该程序下面的这个版本很明显是正确的,而且它比最初的版本要更易于理解。它将打印出如你所期望的Hello World:

public class StrungOut {
public static void main(String[ ] args) {
MyString s = new MyString("Hello world");
System.out.println(s);
}
}
class MyString {
private final java.lang.String s;
public MyString(java.lang.String s) { this.s = s;}
public java.lang.String toString() { return s;}
}


宽泛地讲,本谜题的教训就是要避免重用类名,尤其是Java平台类的类名。千万不要重用java.lang包内的类名,相同的教训也适用于类库的设计者。Java平台的设计者已经在这个问题上栽过数次了,著名的例子有java.sql.Date,它与java.util.Date和org.omg.CORBA.Object相冲突。与在本章中的许多其他谜题一样,这个教训是有关你在除了覆写之外的其他情况应该避免名字重用这一原则的一个具体实例。对平台实现者来说,其教训是诊断信息应该清晰地解释失败的原因。VM应该可以很容易地将没有任何具有正确签名的main方法的情况与根本就没有任何main方法的情况区分开。
2
1
分享到:
评论

相关推荐

    Java解惑PPT7

    接着是Puzzle 67:对字符串上瘾。在这个例子中,自定义了一个名为String的类,这实际上是一个不好的实践,因为它可能会引起混淆,特别是当它与内置的java.lang.String类交互时。在Java中,应该避免使用已存在的类名...

    Java解惑(谜题)CHM中英文双版本

    谜题67:对字符串上瘾 谜题68:灰色的阴影 谜题69:黑色的渐隐 谜题70:一揽子交易 谜题71:进口税 谜题72:终极危难 谜题73:你的隐私正在公开 谜题74:同一性的危机 谜题75:头还是尾? 名字重用的术语表...

    java的正规表达式的java工具类

    不包括特殊字符的匹配 (字符串中不包括符号 数学次方号^ 单引号' 双引号" 分号; 逗号, 帽号: 数学减号- 右尖括号> 左尖括号反斜杠\ 即空格,制表符,回车符等 10 匹配非负整数(正整数 + 0) 11 匹配不包括零的非负...

    一个java正则表达式工具类源代码.zip(内含Regexp.java文件)

    22. 匹配由26个英文字母的大写组成的字符串 23 匹配由26个英文字母的小写组成的字符串 24 匹配由数字和26个英文字母组成的字符串; 25 匹配由数字、26个英文字母或者下划线组成的字符串; java源码: /* * Created ...

    超级关闭:针对标签上瘾者的浏览器加载项,可根据域名或关键字关闭标签

    例如,如果您打开了许多Facebook选项卡,但没有按顺序打开,则可以使用此扩展名,输入“ facebook.com”,按Enter键,瞧,所有包含字符串'facebook.com'的Facebook选项卡都已关闭!本地建筑安装依赖项npm install ...

    编程小白的第一本 Python 入门书

    初学者需要了解Python中变量的使用、基本的数据类型(如整型、浮点型、字符串等),以及如何进行基本的输入输出操作。此外,Python中的控制结构,包括条件语句(if-else)和循环语句(for和while循环)也会是书中...

    red-screen-game:用户必须走到最后的互动游戏

    2015 年 2 月 1 日 - 不是删除 URL,而是将 URI 模式更改为 SecureRandom.hex(3),因此每个页面都将是一个随机字符串 - 删除了 /paths/ url,因为它在 url 中不需要 - 添加了警告elipesy 由于闪烁的颜色 - 添加了...

    2048电脑版源码

    此外,描述中提到的“不支持存档”意味着游戏进度无法保存,这在实际开发中可以通过实现序列化和反序列化功能来解决,将当前棋盘状态转化为字符串存储,下次游戏启动时再反序列化恢复。音乐方面,"半成品"可能指的是...

    js 写2048网页游戏

    此外,还可以考虑使用ES6的语法特性,如箭头函数和模板字符串,以简化代码。 总结,创建2048游戏涉及了JavaScript的数组操作、事件处理、DOM操作,以及CSS的布局和样式设计。通过这个项目,开发者不仅可以提升...

    leetcode卡-leetcode-log:这是个人leetcode记录,每天做

    leetcode卡 Leetcode 打卡日志 (Java) 个人打卡 ...第六周(字符串/easy)2020-01-13 ~ 2020-01-19 第七周(动态规划/easy)2020-01-20 ~ 2020-01-26 春节,有点懈怠了。 第八周(栈/easy&medium)

    2048安卓源码

    8. **多语言支持**:如果游戏支持多种语言,源码会包含字符串资源文件,用于国际化和本地化。 9. **版本控制**:作为一个项目,2048的源码可能使用Git等版本控制系统进行版本管理和协同开发。 通过分析和理解这个...

    LIVE555 拉取H264 支持账号密码实现(三)

    它会根据给定的用户名和密码生成Base64编码的认证字符串。 然后,我们使用`RTSPClient`对象向服务器发送`DESCRIBE`请求,获取媒体描述信息,这包含了H264视频流的解码参数。一旦收到响应,我们解析SDP(Session ...

Global site tag (gtag.js) - Google Analytics