Java中的变量阴影

Pra*_*gla 39 java

我对这个Java代码有些怀疑.它给出的输出是"毛茸茸的bray".我的问题:

  1. 为什么我得到这个输出?
  2. 如何在ZooKeeper类中访问String对象引用"name"?
  3. 如果它与变量阴影有关,那么哪个变量被遮蔽?

码:

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?
   }
 }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 63

变量不是多态的.当您访问时m.name,无论对象的执行时类型如何,它都将始终使用Mammal.name属于该对象的字段.如果需要访问Zebra.name,则需要一个编译时类型为的表达式Zebra.

makeNoise虚拟地调用该方法 - 在执行时使用的实现确实取决于对象的类型.

请注意,如果您将所有字段设为私有 - 这通常是一个好主意 - 这不会成为一个问题.

这实际上是隐藏而不是遮蔽.有关隐藏的详细信息,请参阅JLS第8.3 节;有关阴影的信息,请参见第6.4.1节.我不能说我总是保持差异......

  • 因此,为了正确输出,您必须创建一个getter方法,如`public String getName(){return this.name;}` (5认同)
  • @PLB:我会把它变成超类中的*private*字段 - 但它取决于所需要的.我们在这里并没有真正的用例,并解释了两个独立字段的含义. (2认同)

Vis*_*l K 15

输出来自"毛茸茸的bray".请解释一下.

fields在java程序中不能通过动态查找访问.相反,它们在编译时静态解析.这就是为什么你所得到furry的m.name.然而,methods在java程序中通过动态查找来访问.这就是为什么你所得到bray的m.makeNoise().

我们如何访问名称变量,其中有"条纹"?

如果你想访问Zebra.name,你应该输入m'Zebra'.这看起来像这样:

System.out.println(((Zebra)m).name + m.makeNoise());
Run Code Online (Sandbox Code Playgroud)

更新
此处展示的现象是字段隐藏而不是可变阴影的结果.


blo*_*mon 9

Java中没有变量覆盖,您在父项和子项中都声明了名称,但是您通过父引用变量引用了它.这就是你为什么"毛茸茸"的原因.

最重要的是方法,这就是为什么你有勇气.因为在运行时它会查看堆中的真实对象并看到它是Zebra.