Trouble trying to grasp inheritance

前端 未结 3 1369
南方客
南方客 2021-01-07 03:45

Given Main.java:

public class Main{
    public static void main(String[]args){
          A a = new B();
          a.print();
    }

}

class A{
       A() {p         


        
相关标签:
3条回答
  • 2021-01-07 04:30

    B doesn't have any constructor, so its default constructor won't do anything except calling A's constructor.

    Now when B's default constructor is called, it calls A's constructor (keep in mind i is still not set, so default value 0). A's constructor calls print(), now as object is of actually B it calls B's print() and it prints 0 (remember i was not set).

    Now once these constructor calls completes B's code gets executes which sets i to 0. Now calling print() will again get you to B's print() (as object is of B only) which will print 4.

    "DEBUGGING IS THE KEY"

    0 讨论(0)
  • 2021-01-07 04:51

    In case of Overridden methods (like print() in your example), object type decides which method to be invoked, not the reference type.

    0 讨论(0)
  • 2021-01-07 04:52

    Calling a.print() prints 4 because of polymorphism. The method called depends on the runtime type of a, which is B. It doesn't matter when it's called; polymorphism applies always.

    Both times, B's print method is called. Once is from A's constructor, which is called by the default constructor in B. The other time is your explicit call in main.

    The reason that the first printing yields 0 and not 4 is because at the time that print is called, A is still being constructed. That is, the A constructor is still being executed. Before a superclass constructor returns, nothing is initialized in the subclass yet, not even variable initializers. The value 4 is assigned after the superclass constructor completes, but before the rest of the subclass constructor completes. Because the variable initializers haven't run yet, the default value of 0 (it would be false for booleans and null for objects) is the value of i in the first printing.

    This order is listed by the JLS, Section 12.5:

    Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

    1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

    2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

    3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

    4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

    5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

    (bold emphasis mine)

    This is an example of why it's a bad idea to call a method that can be overridden from a constructor. The subclass state isn't initialized yet.

    0 讨论(0)
提交回复
热议问题