Search code examples
javaoop

Why is "this" being implicitly passed as a parameter whenever trying to invoke a constructor or a method?


Consider this block of java code

    Public class MyClass {
       public void method(int a) {
            doSometing() ;
       }
      Public static void main(String[] args) {
          MyClass obj = new MyClass() ;
          int a = 0 ;
          obj.method(a) ; 
     }
    }

Apparently in java , whenever trying to invoke a constructor or a method it turns out that there is actually another value being implicitly passed by Java other than the explicit one passed by the Developer , which is "this" and I am familiar with the notion of "this" keyword in java but I think it is redundant for "this" to be passed to the method or the constructor implicitly if ive already declared which object this method belongs to, so why would the keyword "this" has to be passed ? , So in the example above Ive declared a class "MyClass" and a method in that class "method" with a return type of "void" then in the main function im declaring a new instance of that class "obj" and calling the method "method" passing the variable "a" as a parameter , so what is actually happening behind the scenes that when declaring a new instance of a class and invoking it`s constructor there is actually a parameter being passed implicitly which is the "this" keyword , so thats what it really looks like behind the scenes :

MyClass obj = new MyClass(this) ;

and the same thing applies when invoking the method :

obj.method(this,a) ;

Thats it , so please can anyone help me with that cuz im tryna learn java and I need to make sure that everything`s clear to me before I proceed any further to Advanced Topics

Thank you


Solution

  • Probably the most direct way to understand why you need to implicitly pass the this reference to every non-static function you call is to show you how such a function call works 'under the hood'.

    Let's take a simple example like

    class Test {
        public void foo(int arg) {}
        public static void bar(int arg) {}
        public void baz() {
            foo(1);
            bar(2);
        }
    }
    

    Now what is the difference between foo and bar?
    The non-static function foo gets executed in the context of an object, while the static bar doesn't have such a context. That means that foo would be able to read and write any fields within that object, bar would not.

    While Java as a language knows about the context of any function you call, the Java Virtual Machine (JVM) that actually executes the code does not directly differentiate between static and non-static functions and does not know any call contexts. (Yes, this is a bit of a semantics question, since it differentiates between static and dynamic binding which is mostly the same as static/non-static functions)

    So when you call a non-static method, the call context (i.e. the object on which the method is called) needs to be provided as an implicit parameter, which is called this.

    The JVM bytecode for the example above is then the following:

    public void baz();
    Code:
       0: aload_0           // Push 'this' as the first parameter onto the stack
       1: iconst_1          // Push 1 as the second parameter onto the stack
       2: invokevirtual #2  // Call 'foo'
       5: iconst_2          // Push 2 as the first parameter onto the stack
       6: invokestatic  #3  // Call 'bar'
       9: return 
    

    You see that for a static function, you only push the parameter onto the stack (which is then popped by the subsequent invoke), for non-static functions, you first push this onto the stack, which was also the first argument of the baz function call (aload stands for argument load)