谜题66:一件私事
class Base{
public String className = "Base";
}
class Sub extends Base{
private String className = "subclass";
}
public class PrivateMatter {
public static void main(String[] args) {
System.out.println(new Sub().className);
}
}
注意该程序有编译错误。因为子类中的变量比父类中的变量更具限制性的访问权限。而子类的变量是private,访问不了。尽管父类的变量被隐藏了,但是可以通过将子类实例转化为父类来访问它,如下可以打印出Base:System.out.println(((Base)new Sub()).className);
一旦一个方法在子类中被覆盖,你就不能在子类的实例上调用它了(除了在子类内部,通过使用super关键字的方法),然而,你可以通过将子类实例转化为父类来访问被隐藏的域。
谜题67:对字符串上瘾
public class StrungOut {
public static void main(String[] args) {
String s = new String("hello");
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;
}
}
运行会出现下图错误并报异常:java.lang.NoSuchMethodError: main
VM找不到main方法,是因为它并不在那里。一个main方法必须接受一个单一的字符串参数,而此程序中String是我们自己定义的String类,而非java.lang.String类。
谜题68:灰色的阴影
public class Shade {
public static void main(String[] args) {
System.out.println(X.Y.Z);
}
}
class X{
static class Y{
static String Z = "Black";
}
static C Y = new C();
}
class C{
String Z= "White";
}
输出的是White。有一条规则决定着程序的行为,即当一个变量和一个类型具有相同的名字,并且它们位于相同的作用域时,变量名具有优先权。相似的,变量名和类型名可以遮掩包名。
注意:编程习惯,变量名小写,类名大写
谜题71:进口税
import static java.util.Arrays.toString;
public class ImportDuty {
public static void main(String[] args) {
printArgs(1,2,3,4,5);
}
static void printArgs(Object...args) {
System.out.println(toString(args));
}
}
编译错误,Arrays.toString(Object[])可以完全匹配,为啥出错呢?本例中toString引用的是Object继承而来的toString方法。简单地说,
本身就属于某个范围的成员在该范围内与静态导入相比具有优先权。
可改为:
import java.util.Arrays;
public class ImportDuty {
public static void main(String[] args) {
printArgs(1,2,3,4,5);
}
static void printArgs(Object...args) {
System.out.println(Arrays.toString(args)); //[1, 2, 3, 4, 5]
}
}
谜题:
class Base {
public static final String PRIZE = "$64,000";
}
public class Sub extends Base {
public static final String PRIZE = "2 cents";
public static void main(String[] args) {
System.out.println(Sub.PRIZE); // 2 cents
}
}
编译成功并打印出2 cents。
final修饰符对方法和域而言,意味着某些完全不同的事情。对于方法,final意味着该方法不能被覆写(对实例方法而言)或者隐藏(对静态方法而言)。对于域,final意味着该域不能被赋值超过一次。