Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么它在子类对象中存储或分配超级类变量的内存?_Java_Inheritance_Polymorphism_Subclass_Superclass - Fatal编程技术网

Java 为什么它在子类对象中存储或分配超级类变量的内存?

Java 为什么它在子类对象中存储或分配超级类变量的内存?,java,inheritance,polymorphism,subclass,superclass,Java,Inheritance,Polymorphism,Subclass,Superclass,在下面的代码中- class Mammal { String name = "furry "; String makeNoise() { return "generic noise"; } } class Zebra extends Mammal { String name = "stripes "; String makeNoise() { return "bray"; } } public class ZooKeeper {

在下面的代码中-

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());

      Zebra z = new Zebra();
      System.out.println(z.name + z.makeNoise());
   }
}
如果我在eclipse的调试窗口中看到,这两个对象(
m
z
)都包含
name
变量(
furry
stripes
)的值


我知道在多态性中,子类也可以使用超类的泛型方法。但为什么子类对象也存储超类变量的值,即使是在隐藏的情况下。这有什么用吗

首先:一般来说,如果类定义了子类可以访问的字段,则子类不应重新定义该字段。这真是个坏主意。您看到的主要功能是使private字段正常工作。在子类中重新定义非私有字段是在寻求一个伤害的世界。(当然,如果乔写的是
哺乳动物
,玛丽写的是
斑马
,乔在
哺乳动物
中添加了一个字段,该字段恰好与玛丽在
斑马
中使用的字段冲突,玛丽对此无能为力。这是将所有字段设置为私有的原因之一。)

但为什么子类对象也存储超类变量的值,即使是在隐藏的情况下

这里的关键是要记住字段不是多态的,只是方法。因此,对象中必须有两个
名称
字段(一个来自
哺乳动物
,一个来自
斑马
),因为使用
哺乳动物
类型引用的代码需要查看
哺乳动物
名称,而使用
Zebra
类型引用的代码需要查看
Zebra
名称

这就是为什么你的代码显示“毛茸茸的叫声”,然后显示“条纹叫声”。您通过
m
获得“furry bray”,因为在
m
上访问
name
(一个
哺乳动物
-类型变量)访问
哺乳动物
名称
(非多态),会给您“furry”。但随后您使用
m
调用方法
makeNoise
,并返回
“bray”
,因为调用的方法是
Zebra
(多态)上的方法。然后用
z
(一个
Zebra
-键入的引用)再次执行此操作,并看到“条纹嘶鸣”,因为
z
访问
Zebra
名称,而不是
哺乳动物的


下一个问题是:如果我们将两个类中的
makeNoise
更改为:

String makeNoise() { 
    return this.name;
}
为什么动物园管理员的代码

  Mammal m = new Zebra();
  System.out.println(m.name + m.makeNoise());

  Zebra z = new Zebra();
  System.out.println(z.name + z.makeNoise());
m
z
给我们提供“毛茸茸的条纹”

这是同样的原因,只是不同的表现
m.name
哺乳动物
类型的引用中访问
名称
,从而查看
哺乳动物
名称
(非多态性)
m.makeNoise
调用
Zebra
makeNoise
方法(多态),在
Zebra
内部
makeNoise
这个
具有
斑马
类型,即使我们从
哺乳动物中调用它(因此,
this.name
使用了
Zebra
name
)。Zebra的
makeNoise
在那里被使用,以及
Zebra
中的
this
代码被键入
Zebra
这一事实都是Java多态性的关键

让我们更进一步:如果
Zebra
根本没有定义
makeNoise
,该怎么办

class Mammal {
    String name = "furry ";
    String makeNoise() { 
        return this.name;
    }
}

class Zebra extends Mammal {
    String name = "stripes ";
}
现在我们从
m
中得到“毛茸茸的”和从
z
中得到“条纹毛茸茸的”。其原因与上面相同:引用的类型决定使用哪个字段,在
哺乳动物
代码中(
makeNoise
),
this
的类型为
makeNoise
。因此,尽管我们使用
z
调用了
makeNoise
,但由于
Zebra
没有
makeNoise
哺乳动物的类型被调用,因此查找
name
的引用的类型为
makeNoise

这有什么用吗


类的正常工作是至关重要的,尤其是在私有字段的情况下。
哺乳动物
代码不必担心出现子类并重新定义其字段。您可以有10个深的类层次结构,每个类定义自己的
名称
,这很好,每个级别的代码都可以使用它定义的
名称

没有子类对象和超类对象。只有一个对象。当你做
new Zebra()
时,你会得到一个
Zebra
(它本身也是
哺乳动物
)。您没有得到一个
Zebra
对象和另一个
Madama
对象。这是因为您声明了
name
两次:
Zebra.name
“隐藏”
Madama.name
-它不是同一个变量。请从Zebra中删除声明,并将赋值放入Madama的构造函数中以使用同一个变量(不仅仅是一个同名的)。只有一个物体,斑马也是哺乳动物,但在某个地方没有独立的哺乳动物物体,漂浮在周围。它还要把它们放在哪里?你的问题没有意义。