How do common Java methods work under the hood?

Let me first admit that I'm not a lot of Java programmers. I come from a C ++ perspective, look at another user's code and wonder ... how does it work?

C ++ has template member functions similar to common Java methods, but template functions in C ++ cannot be virtual — that is, they cannot be redefined. This restriction makes sense to me, because virtual (redefined) functions are ultimately pointers to functions, and if it is possible for a virtual function to be built, the class definition could not know how many function pointers it generates for itself.

But Java general methods, on hand, seem to be perfectly fine, redefined by a derived class. How does Java do this?

+4
source share
2 answers

As far as I can tell, the C ++ compiler creates an instance (implicitly or explicitly) for a given template argument, and at run time we have different functions for each template argument.

There is no such thing as generalization or specialization in Java. For instance,

public class MyClass{

    public void <T> method(T t){ }

}

We cannot create and specialize it somehow in C ++

public void <Integer> MyClass::method(Integer t){ //not valid in Java
   //...
}

Instead, type erasure came, so at run time we have one non-generated version of the generic method that you can override.

Take a look at this simple class:

public class Main{

    public static void main(String[] args){

        Main m = new Main();
        m.method(10);
        m.methodNumber(10);
        m.methodNumberAnd(10);
        m.methodNumberAnd2(10);
        m.methodInteger(10);
    }
    public <T> void method(T t){ }
    public <T extends Number> void methodNumber(T t){ }
    public <T extends Number & java.io.Serializable> void methodNumberAnd(T t){ }
    public <T extends java.io.Serializable & java.lang.Comparable<T>> void methodNumberAnd2(T t){ }
    public void methodInteger(Integer t){ }
}

And run

javac Main.java
javap -c Main.class

He gives the following:

public class Main {
  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class Main
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: bipush        10
      11: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      14: invokevirtual #5                  // Method method:(Ljava/lang/Object;)V
      17: aload_1
      18: bipush        10
      20: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      23: invokevirtual #6                  // Method methodNumber:(Ljava/lang/Number;)V
      26: aload_1
      27: bipush        10
      29: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      32: invokevirtual #7                  // Method methodNumberAnd:(Ljava/lang/Number;)V
      35: aload_1
      36: bipush        10
      38: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      41: invokevirtual #8                  // Method methodNumberAnd2:(Ljava/io/Serializable;)V
      44: aload_1
      45: bipush        10
      47: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      50: invokevirtual #9                  // Method methodInteger:(Ljava/lang/Integer;)V
      53: return

  public <T> void method(T);
    Code:
       0: return

  public <T extends java.lang.Number> void methodNumber(T);
    Code:
       0: return

  public <T extends java.lang.Number & java.io.Serializable> void methodNumberAnd(T);
    Code:
       0: return

  public <T extends java.io.Serializable & java.lang.Comparable<T>> void methodNumberAnd2(T);
    Code:
       0: return

  public void methodInteger(java.lang.Integer);
    Code:
       0: return

}

Pay attention to the signatures of the compiled methods:

Method method:(Ljava/lang/Object;)V
Method methodNumber:(Ljava/lang/Number;)V
Method methodNumberAnd:(Ljava/lang/Number;)V
Method methodNumberAnd2:(Ljava/io/Serializable;)V
Method methodInteger:(Ljava/lang/Integer;)V

As @Eugene notes, generic types will be erased with the first type binding in the case &.

+2
source

++ .

Java , Object. Object - .

public class A<T> {
    public T f(T x) { return x; }
}

public class B extends A<String> {
    @Override
    public String f(String s) { return s.toLowerCase(); }
}

, - :

public class A {
    public Object f(Object x) { return x; }
}

public class B extends A {
    @Override
    public Object f(Object x) { return B.this.f((String)x); }

    public String f(String s) { return s.toLowerCase(); }
}

++ , .

Java .class , ++.o .obj, : : . "" . jvm- .

+2

Source: https://habr.com/ru/post/1692691/


All Articles