简体   繁体   English

Java中的继承如何工作?

[英]How does inheritance in Java work?

We have next classes: 我们有下一堂课:

class Super {
    void foo() {
        System.out.println("Super");
    }
}

class Sub extends Super {
    void foo() {
        super.foo();
        System.out.println("Sub");
    }
}

public class Clazz {
    public static void main(String[] args) {
        new Sub().foo();
    }
}

Output is: 输出是:

Super

Sub

Questions: 问题:

What does super present? super礼物是什么? Is it object of parent class, which child keeps as field? 它是父类的对象,哪个孩子保持为字段?

  • If it is, how does inheritance of abstract classes work? 如果是,抽象类的继承如何工作? You can not create instance of abstract class. 您无法创建抽象类的实例。
  • If it is not, where are overridden method hold? 如果不是,那么被覆盖的方法在哪里举行?

I tried to Google, but all I found is common information about how to inherit classes and so on. 我试过谷歌,但我找到的只是关于如何继承类等的常见信息。

Update: 更新:

You are still telling me obvious things. 你还在告诉我显而易见的事情。 Maybe my question was little misleading, but I'll try to rephrase it: 也许我的问题有点误导,但我会试着改写它:

  • When we are calling method with super , you say, we are accessing parent's method. 当我们用super调用方法时,你说,我们正在访问父方法。 But how can we call this method without parent's object? 但是如何在没有父对象的情况下调用此方法呢?
  • Is super same as this ? superthis this is a reference to concrete object, as you know. 如您所知, this是对具体对象的引用。

The child class does not maintain any special field representing its parent. 子类不维护任何表示其父级的特殊字段。 You may be thinking something along the lines of inner classes, which do maintain a reference to their outer class. 你可能正在思考内部类的某些东西,它们确实维护了对它们外部类的引用。 This is a special case and does not represent how super-sub classes relate to each other. 这是一种特殊情况,并不代表超级子类彼此之间的关系。

Internally, the JVM maintains a 'method table', associating each class its loaded with the methods available for that class. 在内部,JVM维护一个'方法表',将其加载的每个类与该类可用的方法相关联。 The JVM also knows about the relationships between all classes its loaded, including super-sub relationships. JVM还知道它加载的所有类之间的关系,包括超子关系。

When you invoke a super function, the JVM actually does a couple of things: 当您调用super函数时,JVM实际上做了以下几件事:

  • Determines the parent of the class that the method is is being called from 确定要从中调用方法的类的父级
  • Determines the method on the parent that will be called 确定将要调用的父级的方法
  • Invokes the method, with a special instruction ( invokespecial ) 使用特殊指令调用该方法( invokespecial

If you were to examine the class file for your Sub class, you would see something like this for the foo method: 如果您要检查Sub类的类文件,您会看到foo方法的类似内容:

void foo();
    flags: 
    Code:
        stack=2, locals=1, args_size=1
            0: aload_0       
            1: invokespecial #2        // Method Super.foo:()V
            4: getstatic     #3        // Field java/lang/System.out:Ljava/io/PrintStream;
            7: ldc           #4        // String Sub
            9: invokevirtual #5        // Method java/io/PrintStream.println:(Ljava/lang/String;)V

Line 1 in the listing shows the special instruction that invokes the superclass method. 清单中的第1行显示了调用超类方法的特殊指令。

A good source of reading would be the Java Virtual Machine Specification , particularly Section 2.11.8 . 读取的一个很好的来源是Java虚拟机规范 ,特别是第2.11.8节

Okay. 好的。 Let's go, line by line through your code. 我们一行一步地通过您的代码。

Your first statement, in your 'foo' method is 你的'foo'方法中的第一个陈述是

super.foo();

Well that's an explicit call to the superclass foo method. 那是对超类foo方法的显式调用。 Which is: 这是:

 void foo() {
    System.out.println("Super");
}

So "Super" is outputted to the console, becuase you've explicitly called this method with the super keyword. 所以“Super”输出到控制台,因为你已经用super关键字明确地调用了这个方法。 super refers to the class' superclass, in the same way that this refers to the current class. super指的是类的父类,以同样的方式, this指的是当前类。

Next is the rest of the foo method in the subclass: 接下来是子类中foo方法的其余部分:

 void foo() {
    super.foo();
    System.out.println("Sub");
}

Well after super.foo() is called, it's time to move to the next statement, which outputs "Sub". super.foo()之后,是时候转到下一个语句,输出“Sub”。


The reason why your program moves to the subclass' method first, instead of the superclass, is because of a principle called Polymorphism . 你的程序首先移动到子类'方法而不是超类的原因是因为一个叫做Polymorphism的原理。 That is, a subclass takes a method from the superclass, and alters it's behavior. 也就是说,子类从超类中获取一个方法,并改变它的行为。

Abstract Classes 抽象类

You can't create instances of Abstract classes, no, but with the super keyword, you can access the functionality of the superclass nonetheless. 您不能创建Abstract类的实例,不能,但是使用super关键字,您仍然可以访问超类的功能。

In context of the Java Virtual Machine 在Java虚拟机的上下文中

So what happens, when you make a method call, is the Java Virtual Machine will look for the method in the local class, if it is an instance method. 那么,当您进行方法调用时,如果它是实例方法,Java虚拟机将在本地类中查找该方法。 If it can not find it, it will move to the superclass. 如果找不到它,它将移动到超类。 When you use the principle of Polymorphism , the JVM finds the method with the correct signature in the subclass, and stops looking. 当您使用Polymorphism原理时,JVM会在子类中找到具有正确签名的方法,并停止查找。 This is how inheritance and Polymorphism works in simple terms, in the context of Java. 这就是继承和Polymorphism在Java的上下文中以简单的方式工作的方式。

When you override a method, you add a method with the same method signature (the name, number and type of a method's fields) to the subclass definition. 覆盖方法时,可以向子类定义添加具有相同方法签名(方法字段的名称,编号和类型)的方法。 This is how the JVM finds it, and this is where the overridden method is stored. 这就是JVM找到它的方式,这是存储重写方法的地方。

super is a keyword allowing you to call the method implementation defined in the superclass. super是一个关键字,允许您调用超类中定义的方法实现。 It is not a field of your sub-class. 它不是你的子类的一个领域。

If it is not, where are overrided method hold? 如果不是,那么覆盖的方法在哪里举行?

I'm not quite sure what you mean by this, but: 我不太清楚你的意思,但是:

  • the method which prints "Super" is held in the class definition of the superclass 打印“超级”的方法保存在超类的类定义中
  • the method which prints "Sub" is held in the class definition of the subclass. 打印“Sub”的方法保存在子类的类定义中。

Since Sub extends Super , the definition of the Sub class includes a reference to the definition of the Super class. 由于Sub扩展了SuperSub类的定义包括对Super类定义的引用。

Answering updated questions: 回答更新的问题:

When we are calling method with super, you say, we are acessing parent's method. 当我们用super调用方法时,你说,我们正在进行父方法。 But how can we call this method without parent's object? 但是如何在没有父对象的情况下调用此方法呢?

A method is just a block of code, just a sequence of bytecode instructions that we need to execute. 方法只是一个代码块,只是我们需要执行的一系列字节码指令。 When you invoke a method, the JVM's task is to determine, from the method name and parameters you give, where to find this block of code. 当您调用方法时,JVM的任务是根据您提供的方法名称和参数确定在哪里找到此代码块。 Normally, as others have said, it will first look in the class definition of the class of the object on which the method was invoked. 通常,正如其他人所说,它将首先查看调用该方法的对象的类的类定义。 When you use super , you are telling the JVM not to look here, and instead look in the parent class definition. 当你使用super ,你告诉JVM不要看这里,而是查看父类定义。

So you don't need separate instances of Super and Sub , because a Sub is a Super ( new Sub() instanceof Super is true ), and because the JVM knows that the super keyword means that it should look for the code composing a method in the class definition of Super . 因此,您不需要单独的SuperSub实例,因为Sub SuperSuper new Sub() instanceof Supertrue ),并且因为JVM知道super关键字意味着它应该查找构成方法的代码在Super的类定义中。

Is super same as this? 这个超级一样吗? this is a reference to concrete object, as you know. 如您所知,这是对具体对象的引用。

No, they're not the same. 不,他们不一样。 this is a reference to the current object, whereas super is not a reference to an object, instead it is a keyword which affects where the JVM will look for the code defining a method which is being invoked. this是对当前对象的引用,而super不是对对象的引用,而是一个关键字,它影响JVM查找定义正在调用的方法的代码的位置。

when you write super.foo(); 当你写super.foo(); you are calling the superclass method. 你正在调用超类方法。

The foo method of class sub overrides the foo method of Super by adding an instruction to the super class method. class sub的foo方法通过向超类方法添加指令来覆盖Super的foo方法。

foo method override in sub class .super.foo() calling print super and then System.out.println("Sub"); 子类.super.foo()中的foo方法覆盖调用print super,然后调用System.out.println(“Sub”); shows Sub. 显示Sub。

try this for inheritence 试试这个继承

class Super {
    Super()
    {
        System.out.println("1");
    }
    void foo() {
        System.out.println("Super");
    }
}

class Sub extends Super {
    public Sub() {
        // TODO Auto-generated constructor stub
        System.out.println("2");
    }
    void foo() {
       super.foo();
        System.out.println("Sub");
    }
}

There is only one object that is simultaneously a Sub, and a Super, and an Object. 只有一个对象同时是Sub,Super和Object。 It has all the non-static fields for each of those classes. 它具有每个类的所有非静态字段。 A class only really needs one copy of the code for its methods, even the non-static ones. 一个类实际上只需要一个代码副本用于其方法,甚至是非静态代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM