Java中的variables阴影
我对这个Java代码有一些怀疑。 它给出的输出是“毛茸茸的bray”。 我的问题:
- 为什么我得到这个输出?
- 我如何访问ZooKeeper类中的String对象引用“name”?
- 如果它与variables阴影有关,那么哪个variables被阴影?
码:
class Mammal { String name = "furry "; String makeNoise() { return "generic noise"; } } class Zebra extends Mammal { String name = "stripes "; String makeNoise() { return "bray"; } } public class ZooKeeper { public static void main(String[] args) { new ZooKeeper().go(); } void go() { Mammal m = new Zebra(); System.out.println(m.name + m.makeNoise()); //Output comes as "furry bray". Please explain this. //And how can we access the name variable, the one having "stripes " in it. //Does it have something to do with Variable Shadowing? } }
variables不是多态的。 当你访问m.name
,不pipe对象的执行时间types如何,它总是使用作为该对象一部分的Mammal.name
字段。 如果您需要访问Zebra.name
,则需要使用编译时types的Zebra
expression式。
makeNoise
方法被虚拟调用 – 在执行时使用的实现取决于对象的types。
请注意,如果您将所有的字段设置为私有的(无论如何,这通常是一个好主意),这不会成为问题。
这实际上是隐藏而不是阴影。 有关隐藏的详细信息,请参阅JLS第8.3 节 ,阴影部分请参阅第6.4.1节 。 我不能说我总是保持着不同的观点
产量来“毛茸茸的bray”。 请解释一下。
Java程序中的fields
不能通过dynamic查找来访问。 相反,它们是在编译时静态parsing的。 这就是为什么你要furry
的m.name
。 而java程序中的methods
是通过dynamic查找来访问的。 这就是为什么你m.makeNoise()
变得m.makeNoise()
。
我们如何访问名称variables,其中有“条纹”的variables?
如果你想访问Zebra.name
,你应该inputm
到'Zebra'。这看起来像这样:
System.out.println(((Zebra)m).name + m.makeNoise());
UPDATE
这里展示的现象是场隐藏的结果,而不是变化的阴影 。
在Java中没有variables重写,在父类和子类中声明了名称,但是通过父引用variables引用它。 这就是为什么你“毛茸茸的”。
有压倒一切的方法,这就是为什么你bray。 因为在运行时,它看着堆中的真实对象,看到它是斑马线。
Java中的variables名称是由引用typesparsing的,而不是它们所引用的对象。 所以,m.name是指哺乳动物中的variables名,即使面团m也是斑马。
这是因为你的Mammal
的name
只是来自Zebra
的name
字段。 然后您可以简单地通过转换为所需的types来访问它。
另一方面, makeNoise()
方法覆盖父类中的同一个方法,所以不能从父类访问实现。