首页 | 论文 | 考试 | 软件 | 新闻 | 读书 | 出国 | 娱乐 | 心理 | 求职 | 学生博客 | 软件站镜像 | 论坛 | BT站
考试首页    基础教育类 | 专升本类 | 硕士学历类 | 外语类考试 | 职业资格认证 | 会计类考试 | 建筑工程类 | 医药类考试 | 外贸类考试 | 计算机类考试
外语考试    托福 雅思 CET 46 商务英语 GRE LSAT PETS GMAT 商业托福 职称英语 金融英语 MSE 专四专八 口译笔译 实用英语 小语种 经典译文 生活英语
会计考试    从业资格 会职 注会 税务师 资产评估 高会 经济师 ACCA/CAT 精算师 房产估价 土地估价   IT认证   等级 水平 微软 思科 Oracle Linux JAVA
职业资格    证券 公务员 导游 保险 司法 人力资源 商务师 教师 秘书 电子商务 项目管理师 律师 护士 医师 药师 报关员 外销员 物流 报检员/货代 期货
学历考试    中考 高考 成人高考 自学考试 双学位    硕士学历   同等学历 MBA EMBA/MPA 法律硕士 考研 会计硕士 在职硕士 教育硕士 工程硕士 研修班
建筑工程    建造师 造价师 建筑师 结构工程师 监理工程师 咨询工程师 城市规划 安全师 室内设计师 岩土工程师 质量资格 土地登记代理人 企业法律顾问
JAVA资格 JAVA动态JAVA指导JAVA题库考试论坛学生博客资料下载微软认证思科认证Oracle认证
  热门资料下载软件水平 | 计算机等级 | 微软认证 | Cisco认证 | Java认证 | Unix认证 | Oracle认证 | Solaris认证 | 编程开发 | 图形图像 | 更多..
您现在的位置:考试 > 计算机考试 > JAVA资格 > JAVA指导 > 文章内容

Java更多的类谜题66:一件私事

来源:考试大    [ 2006-06-01 13:48:57 ]    责任编辑:水自流
在下面的程序中,子类的一个域具有与超类的一个域相同的名字。那么,这个程序会打印出什么呢?
class Base {
    public String className = "Base";
}

class Derived extends Base {
    private String className = "Derived";
}

public class PrivateMatter {
    public static void main(String[ ] args) {
        System.out.println(new Derived().className);
    }
}

对该程序的表面分析可能会认为它应该打印Derived,因为这正是存储在每一个Derived实例的className域中的内容。

更深入一点的分析会认为Derived类不能编译,因为Derived中的className变量具有比Base中的className变量更具限制性的访问权限。

如果你尝试着编译该程序,就会发现这种分析也不正确。该程序确实不能编译,但是错误却出在PrivateMatter中。

如果className是一个实例方法,而不是一个实例域,那么Derived.className()将覆写Base.className(),而这样的程序是非法的。一个覆写方法的访问修饰符所提供的访问权限与被覆写方法的访问修饰符所提供的访问权限相比,至少要一样多[JLS 8.4.8.3]。

因为className是一个域,所以Derived.className隐藏(hide)了Base.className,而不是覆盖了它[JLS 8.3]。对一个域来说,当它要隐藏另一个域时,如果隐藏域的访问修饰符提供的访问权限比被隐藏域的少,尽管这么做不可取的,但是它确实是合法的。事实上,对于隐藏域来说,如果它具有与被隐藏域完全无关的类型,也是合法的:即使Derived.className是GregorianCalendar类型的,Derived类也是合法的。

在我们的程序中的编译错误出现在PrivateMatter类试图访问Derived.className的时候。尽管Base有一个公共域className,但是这个域没有被继承到Derived类中,因为它被Derived.className隐藏了。在Derived类内部,域名className引用的是私有域Derived.className。因为这个域被声明为是private的,所以它对于PrivateMatter来说是不可访问的。因此,编译器产生了类似下面这样的一条错误信息:

PrivateMatter.java:11: className has private access in Derived
        System.out.println(new Derived().className);
                                               ^

请注意,尽管在Derived实例中的公共域Base.className被隐藏了,但是我们还是可以通过将Derived实例转型为Base来访问到它。下面版本的PrivateMatter就可以打印出Base:

public class PrivateMatter {
    public static void main(String[] args) {
        System.out.println(((Base)new Derived()).className);
    }
}

这说明了覆写与隐藏之间的一个非常大的区别。一旦一个方法在子类中被覆写,你就不能在子类的实例上调用它了(除了在子类内部,通过使用super关键字来方法)。然而,你可以通过将子类实例转型为某个超类类型来访问到被隐藏的域,在这个超类中该域未被隐藏。 转贴于 考试大 http://www.examda.com

[1] [2] [下一页] [尾页]

交流JAVA认证考试经验请JAVA认证论坛>>

 搜索引擎

关于学生大 - 黄金会员 - 广告服务 - 联系我们 - 友情链接 - 会员注册 - 网站合作 -

服务热线:0737-2800345 2800007 传真:0737-2800280 电子邮件:studa@163.net
(C) 2001-2006 学生大网站. 湘ICP备05008911号
喜欢examda.com,请把examda.com告诉你QQ上的5位好友,多谢支持! [设为首页]