Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is getClass() called when we create an object for Inner class?

I am studying the workings of Inner Class and inside its bytecode, I was tracing the stack and couldn't understand why is the getClass() called?
I found a similar question for Lambda function but couldn't understand it.

I did try to understand that is required for no null check, after JDK 8 it's been replaced by a static function called requiredNoNull.

Code :

class Outer{
      class Inner{
      }
      public static void main(String args[]){
            Outer.Inner obj = new Outer().new Inner();
      } 
}

ByteCode:

 public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class Outer$Inner
       3: dup
       4: new           #3                  // class Outer
       7: dup
       8: invokespecial #4                  // Method "<init>":()V
      11: dup
      12: invokevirtual #5                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
      15: pop
      16: invokespecial #6                  // Method Outer$Inner."<init>":(LOuter;)V
      19: astore_1
like image 866
0ne0rZer0 Avatar asked Jul 04 '19 06:07

0ne0rZer0


1 Answers

It's a null check in disguise, nothing more, nothing less. Though, in that particular case it's not really needed and future javac optimize that a little - look at the example below.

May be this will explain the issue better (using java-12, where this getClass hack has been replaced by Objects::requireNonNull):

public class Outer {

    class Inner {

    }

    public void left() {
        Outer.Inner inner = new Outer().new Inner();
    }

    public void right(Outer outer) {
        Outer.Inner inner = outer.new Inner();
    }
}

left method will compile to something (you can look at the byte code yourself) that will not use Objects::requireNonNull, since the creation of Outer happens in place and the compiler can for sure tell that new Outer() instance is not null.

On the other hand of you pass Outer as a parameter, the compiler can't prove that the instance passed is not null for sure, thus Objects::requireNonNull will be present in the byte code.

like image 157
Eugene Avatar answered Oct 05 '22 20:10

Eugene