简体   繁体   中英

left and right objects are evaluated / resolved during runtime or compile-time?

Referring to a book exercise...

Having the following code..

Left left = createLeftInstance ();
Right right = createRightInstance ();

...and keeping in consideration that both the above mentioned methods can return instance of all the sub-classes of Left and Right, in Java the call of the following method...

left.invoke (right);

how is resolved:

  • A) basing on runtime type of left and compile-time of right
  • B) basing on compile-time type of left and runtime of right
  • C) basing on compile-time type of left and compile-time of right
  • D) basing on runtime type of left and runtime of right

Actually, I think that the technically correct answer is "none of the above".

  • At compile time, you need to know the declared types of the left variable ( Left ) and the right variable ( Right ). This will determine which method overload 1 of the Left::invoke method is most applicable to a parameter of type Right .

  • At runtime, the actual type of left will determine which actual method gets called.

So the complete answer is:

E) based on compile-time AND runtime types of left and on the compile-time type of right .

However, I suspect that the point of this question in the textbook is to help you distinguish between compile-time resolution of non-overloaded methods and runtime method dispatching. For that purpose, A) is "correct enough".


1 - To make the determination, the compiler needs to compare Right and its supertypes with the different method overloads of the invoke method declared by Left and its supertypes. If there are multiple overloads, the compiler needs to choose the "most specific applicable" overload.

A) is the correct answer here.

The following code demonstrates that.

    public class Main001 {

        public static void main(String[] args) {
            A right = createRightInstance();
            B left = createLeftInstance();

            left.invoke(right);
            System.out.println("Done!!!");
        }

        public static B createLeftInstance() {
            return new B2();
        }

        public static A createRightInstance() {
            return new A2();
        }

    }

    class A{

    }

    class A1 extends A{

    }

    class A2 extends A1{

    }

    class B{
        public void invoke(A x) {
            System.out.println("Invoking method A on B with argument " + x.getClass().getName());
        }
        public void invoke(A1 x) {
            System.out.println("Invoking method A1 on B with argument " + x.getClass().getName());
        }
        public void invoke(A2 x) {
            System.out.println("Invoking method A2 on B with argument " + x.getClass().getName());
        }
    }

    class B1 extends B{
        public void invoke(A x) {
            System.out.println("Invoking method A on B1 with argument " + x.getClass().getName());
        }
        public void invoke(A1 x) {
            System.out.println("Invoking method A1 on B1 with argument " + x.getClass().getName());
        }
        public void invoke(A2 x) {
            System.out.println("Invoking method A2 on B1 with argument " + x.getClass().getName());
        }

    }

    class B2 extends B1{
        public void invoke(A x) {
            System.out.println("Invoking method A on B2 with argument " + x.getClass().getName());
        }
        public void invoke(A1 x) {
            System.out.println("Invoking method A1 on B2 with argument " + x.getClass().getName());
        }
        public void invoke(A2 x) {
            System.out.println("Invoking method A2 on B2 with argument " + x.getClass().getName());
        }
    }

This example prints

Invoking method A on B2 with argument A2
Done!!!

which means A) is the correct answer.

Why does it mean that?

Well... because:
1) a method from the B2 class is invoked (as the output says) and B2 is the runtime type of left (the compile time type of left is B).
2) a method with parameter A is invoked (note that A is the compile-time type of right ), even though the runtime type of right is A2. Compile time type of right is just the type with which right is declared ie A. Runtime type of right is the actual type of the argument ie A2 (see the output, it says with argument A2 there).

Java has A , it is called single dispatch :

  • the method overload is selected by the compiler, at compile-time (matching the compile-time type of right to the methods offered by the compile-time type of left )
  • the method invocation happens on the runtime type of left - as methods do not disappear, left certainly has a method with the same signature which was picked at compile-time. This act counts as "dispatch", and as it only depends on left (in runtime), it is "single".

Super simple demo using built-in println(Object) and println(char[]) :

char c[]={'a','b','c'};
System.out.println(c);
Object o=c;
System.out.println(o);

It results in something like

 abc [C@1540e19d 

The first line shows that println(char[]) concatenates the array of characters, the second line shows that the exact same array (one can add some check like println(o==c); ) passed as Object in compile-time results in invoking the println(Object) overload, regardless of the runtime type.

B and C probably do not exist.

D is called multiple dispatch , when the method signature is also selected in runtime using the actual runtime type of the arguments, and the selected method is invoked on the runtime type of left . Java does not support that by default, it can be implemented using reflection, here is a single-argument example:

public static void trickyprintln(Object o) throws Exception {
    System.out.getClass().getMethod("println",o.getClass()).invoke(System.out,o);
}

public static void main (String[] args) throws Exception {
    char c[]={'a','b','c'};
    trickyprintln(c);
    Object o=c;
    trickyprintln(o);
}

This one results in

 abc abc 

as println is picked manually, using the runtime type of the argument. So it is possible to do if someone really needs it in Java, but it does not happen automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM