Java解惑学习有感(七)---更多的类之谜

来源:互联网 发布:圆形相片制作软件 编辑:程序博客网 时间:2024/06/06 10:49

谜题66:一件私事

当你在声明一个域、一个静态方法或一个嵌套类型时,如果其名字与基类中相对应的某个可访问的域、方法或类型相同,就会发生隐藏。隐藏是容易产生混乱的:违反包容性的隐藏域在某种意义上是特别有害的。更一般地讲,除了覆写之外,要避免名字重用。

谜题67:对字符串上瘾

要避免重用类名,尤其是 Java 平台类的类名。千万不要重用 java.lang 包内的类名,相同的教训也适用于类库的设计者。Java平台的设计者已经在这个问题上栽过数次了,著名的例子有 java.sql.Date,它与 java.util.Date 和 org.omg.CORBA.Object 相冲突。

谜题68:灰色的阴影

1、在这样的上下文环境中,有一条规则决定着程序的行为,即当一个变量和一个类型具有相同的名字,并且它们位于相同的作用域时,变量名具有优先权。变量名将遮掩(obscure)类型名。相似地,变量名和类型名可以遮掩包名。这条规则真的是相当地晦涩,任何依赖于它的程序都极有可能使它的读者晕头转向。

2、应该遵守标准的命名习惯以避免不同的命名空间之间的冲突,还有一个原因就是如果你违反这些习惯,那么你的程序将让人难以辨认。同样,为了避免变量名与通用的顶层包名相冲突,请使用 MixedCase 风格的类名,即使其名字是首字母缩拼词也应如此。通过遵守这些规则,你就可以确保你的程序永远不会遮掩类名或包名。


谜题69:黑色的渐隐

以下代码:

class X {
static class Y {
static String Z = "Black";
}
static C Y = new C();
}

class C {
String Z = "White";
}

基于谜题64,如何正确的引用到Y类的Z属性!

方法一、(X.Y)null).Z

方法二、static class Xy extends X.Y{ }
public static void main(String[ ] args){
System.out.println(Xy.Z);
}

方法三、public static <T extends X.Y> void main(String[] args){
System.out.println(T.Z);
}

谜题70:一揽子交易

包内私有的方法不能直接被包外的方法声明所覆写。尽管包内私有的访问
权限和覆写结合到一起会导致某种混乱,但是 Java 当前的行为是允许使用包的,
以支持比单个的类更大的抽象封装。包内私有的方法是它们所属包的实现细节,
在包外重用它们的名字是不会对包内产生任何影响的。


谜题71:进口税

1、滥用静态导入工具也会损害可读性,因为这会使得静态成员的类在何处被使用显得非
常不清晰。应该有节制地使用静态导入,只有在非常需要的情况下才应该使用它们

2、要意识到当某个方法的名字已经出现在某个作用域内时,静态导入工具并不能被有效地作用于该方法上。这意味着静态导入不能用于那些与通用接口中的方法共享方法名的静态方法,而且也从来不能用于那些与 Object中的方法共享方法名的静态方法。

谜题72:终极危难

1、final 修饰符对方法和域而言,意味着某些完全不同的事情。对于方法,final 意味着该方法不能被覆写(对实例方法而言)或者隐藏(对静态方法而言)。对于域,final 意味着该域不能被赋值超过一次。关键字相同,但是其行为却完全不相关。

2、要避免在无关的变量或无关的概念之间重用名字。对无关的概念使用有区别的名字有助于让读者和程序员区分这些概念。

谜题73:你的隐私正在公开

重用名字是危险的;应该避免隐藏、遮蔽和遮掩。


谜题74:同一性的危机

1、如果同一个方法的两个重载版本都可以应用于某些参数,那么它们应该具有相同的行为。

2、如果你重载了一个方法,那么一定要确保所有的重载版本行为一致。

比如equals(Object o)和equals(Enigma e)


谜题75:头还是尾?

1、条件操作符(?:)的行为在 5.0 版本之前是非常受限的[JLS2 15.25]。当第二个和第三个操作数是引用类型时,条件操作符要求它们其中的一个必须是另一个的子类型,不然就会报错

2、在 5.0 或更新的版本中,Java 语言显得更加宽大了,条件操作符在第二个和第三个操作数是引用类型时总是合法的。其结果类型是这两种类型的最小公共超类。公共超类总是存在的,因为 Object 是每一个对象类型的超类型

3、应该升级到最新的 Java 平台版本上。较新的版本都包含许多让程序员更轻松的改进,你并不需要费力去学习怎样利用所有的新特性,有些新特性不需要你付出任何努力就可以给你带来实惠。

介绍一下名字重用的术语表

1、覆写 (override )

一个实例方法可以覆写( override )在其超类中可访问到的具有相同签名的所有实例方法 ,从而使能了动态分派( dynamic dispatch );换句话说, VM 将基于实例的运行期类型来选择要调用的覆写方法  。

class Base {
public void f() { }
}
class Derived extends Base {
public void f() { } // overrides Base.f()
}

2、隐藏 (hide)

一个域、静态方法或成员类型可以分别隐藏( hide )在其超类中可访问到的具有相同名字(对
方法而言就是相同的方法签名)的所有域、静态方法或成员类型。隐藏一个成员将阻止其被
继承

class Base {
public static void f() { }
}
class Derived extends Base {
private static void f() { } // hides Base.f()
}

3、重载 (overload)

在某个类中的方法可以重载( overload )另一个方法,只要它们具有相同的名字和不同的签
名。由调用所指定的重载方法是在编译期选定的

class CircuitBreaker {
public void f(int i) { } // int overloading
public void f(String s) { } // String overloading
}

4、遮蔽 (shadow)

一个变量、方法或类型可以分别遮蔽( shadow )在一个闭合的文本范围内的具有相同名字的所有变量、方法或类型。如果一个实体被遮蔽了,那么你用它的简单名是无法引用到它的;根据实体的不同,有时你根本就无法引用到它

class WhoKnows {
static String sentence = "I don't know.";
public static woid main(String[ ] args) {
String sentence = “I know!”; // shadows static field
System.out.println(sentence); // prints local variable
}
}

5、遮掩 (obscure)

一个变量可以遮掩具有相同名字的一个类型,只要它们都在同一个范围内:如果这个名字被用于变量与类型都被许可的范围,那么它将引用到变量上。相似地,一个变量或一个类型可以遮掩一个包。遮掩是唯一一种两个名字位于不同的名字空间的名字重用形式,这些名字空间包括:变量、包、方法或类型。如果一个类型或一个包被遮掩了,那么你不能通过其简单名引用到它,除非是在这样一个上下文环境中,即语法只允许在其名字空间中出现一种名字。遵守命名习惯就可以极大地消除产生遮掩的可能性

public class Obscure {
static String System; // Obscures type java.lang.System
public static void main(String[ ] args) {
// Next line won't compile: System refers to static field
System.out.println(“hello, obscure world!”);
}
}


如果有疑问或者对该博文有何看法或建议或有问题的,欢迎评论,恳请指正!


0 0
原创粉丝点击