Java中的variables阴影

我对这个Java代码有一些怀疑。 它给出的输出是“毛茸茸的bray”。 我的问题:

  1. 为什么我得到这个输出?
  2. 我如何访问ZooKeeper类中的String对象引用“name”?
  3. 如果它与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的Zebraexpression式。

makeNoise方法被虚拟调用 – 在执行时使用的实现取决于对象的types。

请注意,如果您将所有的字段设置为私有的(无论如何,这通常是一个好主意),这不会成为问题。

这实际上是隐藏而不是阴影。 有关隐藏的详细信息,请参阅JLS第8.3 节 ,阴影部分请参阅第6.4.1节 。 我不能说我总是保持着不同的观点

产量来“毛茸茸的bray”。 请解释一下。

Java程序中的fields不能通过dynamic查找来访问。 相反,它们是在编译时静态parsing的。 这就是为什么你要furrym.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也是斑马。

这是因为你的Mammalname只是来自Zebraname字段。 然后您可以简单地通过转换为所需的types来访问它。
另一方面, makeNoise()方法覆盖父类中的同一个方法,所以不能从父类访问实现。