Java谜题7——更多的类谜题
来源:互联网 发布:mac升级系统好吗 编辑:程序博客网 时间:2024/05/21 10:22
Java谜题7__更多的类谜题
谜题66:一件私事 | 谜题67:对字符串上瘾 | 谜题68:灰色的阴影 | 谜题69:黑色的渐隐 | 谜题70:一揽子交易 | 谜题71:进口税 | 谜题72:终极危难 | 谜题73:你的隐私正在公开 | 谜题74:同一性的危机 | 谜题75:头还是尾 | 名字重用的术语表
通过上面的链接可以学习这个章节的各个谜题,下面是学习之后,做的一些笔记。
谜题66:一件私事
首先,复写一个父类的方法的时候,一定要提供给这个域更广泛的访问权限,否则的话就不能实现完美的隐藏。在复写的类里就存在两个可以调用,但是方法名一样的函数,这就是error所在。
其次,强制类型转化也可以完成对父类的方法的调用,即使是在子类中被隐藏的方法!(这说明了覆写与隐藏之间的一个非常大的区别。一旦一个方法在子类中被覆写,你就不能在子类的实例上调用它了(除了在子类内部,通过使用super关键字来方法)。然而,你可以通过将子类实例转型为某个超类类型来访问到被隐藏的域,在这个超类中该域未被隐藏。)
本谜题的教训是隐藏通常都不是一个好主意。Java语言允许你去隐藏变量、嵌套类型,甚至是静态方法(就像在谜题48所展示的那样),但是你不能认为你就应该去隐藏。隐藏的问题在于它将导致读者头脑的混乱。你正在使用一个被隐藏实体,或者是正在使用一个执行了隐藏的实体吗?要避免这类混乱,只需避免隐藏。
总之,当你在声明一个域、一个静态方法或一个嵌套类型时,如果其名字与基类中相对应的某个可访问的域、方法或类型相同,就会发生隐藏。隐藏是容易产生混乱的:违反包容性的隐藏域在某种意义上是特别有害的。更一般地讲,除了覆写之外,要避免名字重用。
谜题67:对字符串上瘾
VM不能找到main方法是因为它并不在那里。尽管StrungOut有一个被命名为main的方法,但是它却具有错误的签名。一个main方法必须接受一个单一的字符串数组参数[JVMS 5.2]。VM努力要告诉我们的是StrungOut.main接受的是由我们的String类所构成的数组,它无论如何都与java.lang.String没有任何关系。
如果你确实需要编写自己的字符串类,看在老天爷的份上,千万不要称其为String。要避免重用平台类的名字,并且千万不要重用java.lang中的类名,因为这些名字会被各处的程序自动加载。程序员习惯于看到这些名字以无限定的形式出现,并且会很自然地认为这些名字引用的是我们所熟知的java.lang中的类。如果你重用了这些名字的某一个,那么当这个名字在其自己的包内被使用时,该名字的无限定形式将会引用到新的定义上。
可以证明,在这样的上下文环境中,有一条规则决定着程序的行为,即当一个变量和一个类型具有相同的名字,并且它们位于相同的作用域时,变量名具有优先权[JLS 6.5.2]。变量名将遮掩(obscure)类型名[JLS 6.3.2]。相似地,变量名和类型名可以遮掩包名。这条规则真的是相当地晦涩,任何依赖于它的程序都极有可能使它的读者晕头转向。
幸运的是,遵守标准的Java命名习惯的程序继续从来都不会遇上这个问题。类应该以一个大写字母开头,以MixedCase的形式书写;变量应该以一个小写字母开头,以mixedCase的形式书写;而常量应该以一个大写字母开头,以ALL_CAPS的方式书写。单个的大写字母只能用于类型参数,就像在泛型接口Map<K,V>中那样。包名应该以lower.case的方式命名[JLS 6.8]。
可以引用到一个被遮掩的类型名的,其技巧就是在某一种特殊的语法上下文环境中使用该名字,在该语法上下文环境中允许出现一个类型但是不允许出现一个变量。在转型表达式的括号中间的部分就是这样一种上下文环境。下面的程序通过使用这种技术解决了这个谜题,并且将打印出我们所期望的Black:
public class FadeToBlack { public static void main(String[] args){ System.out.println(((X.Y)null).Z); }}
不借助这种有问题的用法,而是通过在一个类声明的extends子句中使用一个被遮掩的类这种方式,你也可以解决本谜题。因为基类总是一种类型,出现在extends子句中的名字从来都不会被解析为变量名。
下面的程序就展示了这项技术,它也会打印出Black:
public class FadeToBlack {
public class FadeToBlack { static class Xy extends X.Y{ } public static void main(String[ ] args){ System.out.println(Xy.Z); }}
如果你使用的5.0或更新的版本,那么通过在一个类型变量声明的extends子句中使用X.Y这种方式,你也可以解决本谜题:
public static <T extends X.Y> void main(String[] args){ System.out.println(T.Z); }}
- Java谜题7——更多的类谜题
- Java谜题7——更多的类谜题
- Java谜题7-更多的类谜题
- Java谜题8——更多的库谜题
- Java谜题畅读版之更多的类谜题
- Java谜题畅读版之更多的类谜题
- 《java解惑》读书笔记8——更多类谜题
- Java谜题8-更多的库谜题
- Java 开始篇——新的开始,更多的努力
- Java并发编程——线程池的使用(四)线程池的更多用法
- Java——第四章——类与对象之类的更多细节
- Java 7新特性(三) ——更多NIO APIs
- 《java解惑》读书笔记3——更多字符串之谜
- 实战 Groovy: Groovy:Java 程序员的 DSL——用 Groovy 编写更少的代码,完成更多的工作
- Java谜题畅读版之更多的库谜题
- Java谜题畅读版之更多的库谜题
- 欢迎更多的需要毕设和接毕设的加入! Android/Java毕业设计——唯一QQ群:639813324
- 练习5——更多的变量和打印
- 用js取float型小数点后两位,例22.127456取成22.13
- win7上帝模式
- 我的七个建议
- 数据挖掘方法论crisp-DM
- MFC框架程序中全屏显示特性的实现
- Java谜题7——更多的类谜题
- Oracle 收购Sun之后的演义:IBM 和SAP何去何从
- 如果你能找到这里,一定能感受到我的祝福!
- 数据挖掘方法论-SEMMA
- android围棋游戏开发第三周总结
- 第一篇用于测试
- 不显示删除回复显示所有回复显示星级回复显示得分回复 [推荐] 从少林寺的核心竞争力看软件作坊和正规军的差异
- glic 编译出错
- 如何子类化(SubclassWindow)窗体