javainheritanceoverridingcontrol-flowmethod-hiding

Instance and Static control-flow with inheritance and overriding/method-hiding


I'm toying around with instance control flow and static control flow, notice the code below

class A {
    {
        m1();
    }
    A(){
        System.out.println("A constructor");
    }
    void m1(){
        System.out.println("A m1");
    }
}
public class Main extends A {
    public static void main(String[] args) throws Exception {
        Main m = new Main();
    }
    void m1(){
        System.out.println("Main m1");
    }
}

The output for the code is:
Main m1
A constructor

I know this is because:
First, static blocks and variables were identified top-to-bottom parent-to-child, in this case there was just a main() that was static.
Second, the static blocks and variable assignments are executed, so main()'s execution starts, and there is an attempt to create a new Main object.
So third, the instance blocks and variables of parent class will be identified. Then they will be executed top-bottom. (After that the constructor of the parent class will run, then the instance blocks and variables of child class will be identified, following which they will be executed top-bottom and finally the child class' constructor will execute).


So the instance block inside A, calls `m1()`. Then, A's constructor executes. Finally, control flow is returned to `main()` and program terminates.
Now, the call to `m1()` from A invoked `m1()` of `Main`. However, had I made both the `m1()` methods static, everything else remaining same, the call to `m1()` from the instance block of A would then have invoked `m1()` of A.

I have two questions(Why? Purely for academic reasons, I'm still learning Java):

  1. When both the m1() methods are non-static, is it possible to invoke A's m1() from the instance block of A? I tried doing a this.m1() but that still invoked Main's m1().(Why?)
  2. When both the m1() methods are static, is it possible to invoke Main's m1() from the instance block of A? (I'm guessing no but I'm not certain).

    I know in the first case, it's overriding taking place, and in the second case it's method hiding. But I'm still not sure how to answer my questions based on that knowledge.

Solution

  • After compilation is done java 8 compiler your code looks like this:

     class A {
               A() {
                  this.m1();  // at runtime this refers to Main class instance
                  System.out.println("A constructor");
               }
            
               void m1() {
                  System.out.println("A m1");
               }
            }
    
    public class Main extends A {
         public Main() { }
    
         public static void main(String[] args) throws Exception {
              Main m = new Main();
              m.m1();
           }
        
           void m1() {
              System.out.println("Main m1");
           }
        }
    

    Now to answer your first question: No. You cannot unless you are creating an instance of A(actual object of A).

    To your second question: after making both m1's static compilation looks like this:

    class A {
       A() {
          m1(); // resolves to A's m1
          System.out.println("A constructor");
       }
    
       static void m1() {
          System.out.println("A m1");
       }
    }
    public class Main extends A {
       public Main() {
       }
    
       public static void main(String[] args) throws Exception {
          new Main();
       }
    
       static void m1() {
          System.out.println("Main m1");
       }
    }
    

    Now no matter which instance(A or Main) you create you will see A's m1 excuted.