- 浏览: 67943 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
最新评论
-
sunwang810812:
这两个方法都对,只不过我个人觉得,泛型方法的主要目的是为了 p ...
java泛型方法的使用 -
a596620989:
第二个方法是不能通过编译的,会报T can't be reso ...
java泛型方法的使用 -
Javakeith:
...
java泛型 -
bannamoon:
两个方法当然有区别了。当你需要应用泛型规则的时候。第二个方法就 ...
java泛型方法的使用 -
luoping0425:
Learning English!
PEACE—宁静
出自 《java puzzle》
在下面的程序中,子类的一个域具有与超类的一个域相同的名字。那么,这个程序会打印出什么呢?
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关键字来方法)。然而,你可以通过将子类实例转型为某个超类类型来访问到被隐藏的域,在这个超类中该域未被隐藏。
如果你想让这个程序打印Derived,也就是说,你想展示覆写行为,那么你可以用公共方法来替代公共域。在任何情况下,这都是一个好主意,因为它提供了更好的封装[EJ Item 19]。下面的程序版本就使用了这项技术,并且能够打印出我们所期望的Derived:
class Base {
public String getClassName() {
return "Base";
}
}
class Derived extends Base {
public String getClassName() {
return "Derived";
}
}
public class PrivateMatter {
public static void main(String[] args) {
System.out.println(new Derived().getClassName());
}
}
请注意,我们将Derived类中的getClassName方法声明成了public的,尽管在最初的程序中与其相对应的域是私有的。就像前面提到的那样,覆写方法的访问修饰符与它要覆写的方法的访问修饰符相比,所具有的限制性不能有任何降低。
本谜题的教训是隐藏通常都不是一个好主意。Java语言允许你去隐藏变量、嵌套类型,甚至是静态方法(就像在谜题48所展示的那样),但是你不能认为你就应该去隐藏。隐藏的问题在于它将导致读者头脑的混乱。你正在使用一个被隐藏实体,或者是正在使用一个执行了隐藏的实体吗?要避免这类混乱,只需避免隐藏。
如果一个类要隐藏一个域,而用来隐藏该域的域具有的可访问性比被隐藏域更具限制性,就像我们最初的程序那样,那么这就违反了包容性(subsumption)原则,即大家所熟知的Liskov置换原则(Liskov Substitution Principle)[Liskov87]。这项原则叙述道,你能够对基类所作的任何事,都同样能够作用于其子类。包容性是面向对象编程的自然心理模型的一个不可分割的部分。无论何时,只要违反了这项原则,就会对程序的理解造成困难。还有其它数种用另一个域来隐藏某个域的方法也会违反包容性:例如,两个域具有不同的类型;一个域是静态的而另一个域不是;一个域是final的而另一个域不是;一个域是常量而另一个域不是;以及两个域都是常量但是它们具有不同的值。
对于语言设计者而言,应该考虑消除隐藏的可能性:例如,使所有的域都隐含地是私有的。如果这样做显得过于严苛,那么至少应该考虑对隐藏进行限制,以使其遵守包容性原则。
总之,当你在声明一个域、一个静态方法或一个嵌套类型时,如果其名字与基类中相对应的某个可访问的域、方法或类型相同,就会发生隐藏。隐藏是容易产生混乱的:违反包容性的隐藏域在某种意义上是特别有害的。更一般地讲,除了覆写之外,要避免名字重用。
在下面的程序中,子类的一个域具有与超类的一个域相同的名字。那么,这个程序会打印出什么呢?
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关键字来方法)。然而,你可以通过将子类实例转型为某个超类类型来访问到被隐藏的域,在这个超类中该域未被隐藏。
如果你想让这个程序打印Derived,也就是说,你想展示覆写行为,那么你可以用公共方法来替代公共域。在任何情况下,这都是一个好主意,因为它提供了更好的封装[EJ Item 19]。下面的程序版本就使用了这项技术,并且能够打印出我们所期望的Derived:
class Base {
public String getClassName() {
return "Base";
}
}
class Derived extends Base {
public String getClassName() {
return "Derived";
}
}
public class PrivateMatter {
public static void main(String[] args) {
System.out.println(new Derived().getClassName());
}
}
请注意,我们将Derived类中的getClassName方法声明成了public的,尽管在最初的程序中与其相对应的域是私有的。就像前面提到的那样,覆写方法的访问修饰符与它要覆写的方法的访问修饰符相比,所具有的限制性不能有任何降低。
本谜题的教训是隐藏通常都不是一个好主意。Java语言允许你去隐藏变量、嵌套类型,甚至是静态方法(就像在谜题48所展示的那样),但是你不能认为你就应该去隐藏。隐藏的问题在于它将导致读者头脑的混乱。你正在使用一个被隐藏实体,或者是正在使用一个执行了隐藏的实体吗?要避免这类混乱,只需避免隐藏。
如果一个类要隐藏一个域,而用来隐藏该域的域具有的可访问性比被隐藏域更具限制性,就像我们最初的程序那样,那么这就违反了包容性(subsumption)原则,即大家所熟知的Liskov置换原则(Liskov Substitution Principle)[Liskov87]。这项原则叙述道,你能够对基类所作的任何事,都同样能够作用于其子类。包容性是面向对象编程的自然心理模型的一个不可分割的部分。无论何时,只要违反了这项原则,就会对程序的理解造成困难。还有其它数种用另一个域来隐藏某个域的方法也会违反包容性:例如,两个域具有不同的类型;一个域是静态的而另一个域不是;一个域是final的而另一个域不是;一个域是常量而另一个域不是;以及两个域都是常量但是它们具有不同的值。
对于语言设计者而言,应该考虑消除隐藏的可能性:例如,使所有的域都隐含地是私有的。如果这样做显得过于严苛,那么至少应该考虑对隐藏进行限制,以使其遵守包容性原则。
总之,当你在声明一个域、一个静态方法或一个嵌套类型时,如果其名字与基类中相对应的某个可访问的域、方法或类型相同,就会发生隐藏。隐藏是容易产生混乱的:违反包容性的隐藏域在某种意义上是特别有害的。更一般地讲,除了覆写之外,要避免名字重用。
发表评论
-
有毒的括号垃圾
2009-05-16 17:01 1079出自《java puzzle》 你能否举出这样一个合法的J ... -
诵读困难者的一神论
2009-05-08 15:17 1088出自《java puzzle》 从前有一个人,他认为世上只 ... -
烧焦到无法识别
2009-05-06 00:01 1025出自《java puzzle》 下面 ... -
反射的污染
2009-04-30 14:25 2469出自《java puzzle》 这个谜题举例说明了一个关于 ... -
异常为循环而抛
2009-04-22 15:33 1058出自《java puzzle》 下面的程序循环遍历了一个i ... -
不情愿的构造器
2009-04-13 23:38 1029出自《java puzzle》 尽管 ... -
不受欢迎的宾客
2009-04-10 13:16 835出自《java puzzle》 本谜题中的程序所建模的系统, ... -
极端不可思议
2009-04-09 13:38 867出自《java puzzle》 本 ... -
同一性的危机
2009-04-08 13:46 743出自《java puzzle》 下面的程序是不完整的,它缺 ... -
你的隐私正在被公开
2009-04-07 22:34 728出自《java puzzle》 私 ... -
终极危难
2009-04-03 11:48 765出自《java puzzle》 本谜题旨在检验当你试图隐藏一 ... -
进口税
2009-04-02 11:08 777出自《java puzzle》 在5.0 ... -
一揽子交易
2009-04-01 10:25 1010出自《java puzzle》 下面这个程序设计在不同的包 ... -
灰色的阴影
2009-03-24 11:33 990出自《java puzzle》 下面 ... -
对字符串上瘾
2009-03-23 10:38 794出自 《java puzzle》 一个名字可以被用来引用位于 ... -
一种疑似排序的惊人传奇
2009-03-19 10:43 685出自《java puzzle》 下 ... -
名字游戏
2009-03-18 15:35 919出自《java puzzle》 下面 ... -
一行的方法
2009-03-14 16:27 875出自《java puzzle》 现 ... -
差是几个
2009-03-12 13:21 739出自《java puzzle》 下面的程序在计算一个int数 ... -
产生它的散列码
2009-03-11 09:35 734出自 《java puzzle》 本 ...
相关推荐
首先,我们来看Puzzle 66:一件私事。这个谜题涉及到了Java中的继承和成员变量的覆盖(overridden)与隐藏(hidden)。在Java中,方法的覆盖要求子类中的方法至少有与父类相同的访问权限,但成员变量没有这样的限制...
谜题66:一件私事 谜题67:对字符串上瘾 谜题68:灰色的阴影 谜题69:黑色的渐隐 谜题70:一揽子交易 谜题71:进口税 谜题72:终极危难 谜题73:你的隐私正在公开 谜题74:同一性的危机 谜题75:头还是尾?...
这是一件私事。” 40. **affect vt. 影响**:动词,表示对事物产生影响或作用。例如,“The weather affected our plans.天气影响了我们的计划。” 41. **afford vt. 负担得起**:动词,表示有足够的资源承担某事...
我有一件紧急且重要的事情需要立即与张总商讨,您能否帮我将电话直接转给他?”这种方式既表达了请求的紧迫性,也展现出了对话者的礼貌和尊重。大多数情况下,秘书或前台人员都不愿意拒绝这样合理且礼貌的要求。 ##...
你需要有一个办法记住这件事,并在未来的某个时间提醒你。 七、保持桌面整洁 我从不相信一个把自己的工作环境弄得乱糟糟的人会是一个优秀的时间管理者。同样的道理,一个人的卧室或是办公室一片狼藉,他也不会是一...
32. **一次性任务完成**:做事时避免分心,一次只做一件事。 33. **检查钱包**:定期整理钱包,避免丢失重要物品。 34. **专注**:将精力集中在一件事情上,提高专注度。 35. **备用垃圾袋**:在垃圾桶底部放置...
同时,耐心让我在处理繁琐的日常事务时更加冷静,也让我意识到,每一件看似简单的事情背后都蕴含着深厚的业务知识。耐心地积累知识、提升技能,是我在实习期间取得进步的秘诀。 总的来说,我的实习经历是宝贵的,它...
第一百五十三至一百五十九条明确了文件的拟稿、核稿、签发、登记、打印、送件、存档等流程。文件的拟稿权责明确,涉及董事会、公司、党内等不同层面的文件分别由相应负责人签发。对于涉密文件,严格遵循保密原则,...
现代企业越来越离不开计算机和网络,基本是人手一台计算机,但是计算机和网络的管理成为一大问题,员工经常用计算机来聊天,做私事、打游戏、下载电影、访问色情网站,这样不仅影响工作,而且对公司文化建设产生不好...
在撰写引言时,应以尊敬的方式称呼收件人,例如“尊敬的院长”或“尊敬的部门经理”,并在第一句话中明确表示撰写此信的目的。紧接着,需要提前通知雇主你的离职意向,这通常需要根据合同中的条款提前两周或更长时间...
比如,当你穿着一件新衣服去公司,你可能会感觉同事们都在注意你的着装,但事实上他们可能更专注于自己的工作或私事。这种错误的自我聚焦会导致我们感到不必要的焦虑和紧张,从而影响我们的行为和表现。认识到这一点...
通过这样的分享,学生们相互启发,互相鼓励,使得阅读不再是一件孤独的事情,而是一个充满乐趣和温馨的交流活动。 在交流读书方法环节中,同学们分享了不同的读书习惯,有的边读边做笔记,有的默读思考。这些高效...
此外,我明白任何时候都不得因私事离开工作岗位,始终保持服务的连续性和专业性。 服务态度是决定客人是否再次选择入住的关键。我始终以耐心、细致的态度对待客人的投诉和询问,力求做到每件小事都能让客人满意。...
在表述这些原因时,应当诚实但不必过于详尽地描述个人私事,以保持专业性和适当的隐私。 其次,对单位及领导表达感激之情是辞职报告中不可或缺的一部分。这一部分展现了辞职者对过去工作经历的尊重和对同事关系的...
近日,我因私事前往垃圾投放点,却因一只邻家看门狗的出现而迟疑不前。这个小小的插曲不仅让我深感恐惧,更让我深刻意识到保护环境的重要性。虽然我很不情愿地扔掉了手中的垃圾,但这件事引发了我对环境问题的深思。...
- **表达诚挚**:对因请假可能对公司运营带来的影响表示歉意,并承诺尽快处理完私事返回工作岗位。 5. **实例分析**: - 示例1:这是一份学生向老师请假的简单例子,说明了受伤导致无法上学,并明确了请假的天数...
此外,该部分还规定了印章的使用流程,要求必须按照既定的公务和私事用途使用,空白文件或未填写内容的文件不允许随意盖章,已盖章的文件必须妥善保存原件或复印件。对于无法再使用的文件,要有销毁记录。证照的使用...
2. **入职手续**:包括填资料卡、提交履历表、身份证复印件和照片,以及佩戴工号牌。 3. **新人培训**:新人需接受在职教育,了解公司规章制度和部门奖金制度。 4. **离职规定**:员工离职需提前一个月书面申请,未...
【进厂事由】列出了多种可能的来访目的,如交货、洽谈、参观、包工、提运货物、公事拜访、私事拜访和其他,根据事由,企业可以预先准备相关资料,安排适当的会议或活动。 【厂商自备工具、物品入厂】这一项关注的是...
- 阐述请假期间的计划,如休息、处理私事,或者如例子中所述“以更好的精力或状态去完成接下来的工作或学习”。 6. **请求批准**: - 在请假条的结尾,要明确提出希望得到批准的意愿,并表示感谢。 7. **签名和...