Why is this Java polymorphism method of a declared type and not a runtime type?

This code:

public class PMTest
{

    private static class Runner { }
    private static class Server extends Runner { }

    private static class Task
    {
        public void delegate(Runner runner)
        {
            System.out.println("Task: " + runner.getClass().getName() +
                               " / " + this.getClass().getName());
        }
    }

    private static class Action extends Task
    {
        public void delegate(Server server)
        {
            System.out.println("Action: " + server.getClass().getName() +
                               " / " + this.getClass().getName());
        }
    }


    private static void foo(Task task, Runner runner)
    {
            task.delegate(runner);
    }

    private static void bar(Action task, Runner runner)
    {
            task.delegate(runner);
    }

    private static void baz(Action task, Server runner)
    {
            task.delegate(runner);
    }


    public static void main (String[] args)
    {
        try {
            Server server = new Server();
            Action action = new Action();

            action.delegate(server);
            foo(action, server);
            bar(action, server);
            baz(action, server);

        }
        catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

produces this conclusion:

$ java PMTest
Action: PMTest$Server / PMTest$Action
Task: PMTest$Server / PMTest$Action
Task: PMTest$Server / PMTest$Action
Action: PMTest$Server / PMTest$Action

I see very clearly that the Tasks method is selected using the Action method. However, I don’t understand why, because objects always know what they are, and I thought that choosing a Java late-binding method could distinguish the difference in method signatures. The call is bar()especially confusing, as it is taskannounced Actionat this point.

If that matters, this is Java 6:

$ java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
BEA JRockit(R) (build R27.6.5-32_o-121899-1.6.0_14-20091001-2113-linux-ia32, compiled mode)

I can change my code so that it works, but I would like to understand why it does not work. Thanks for the help!

+3
source share
3 answers

How submission works in java.

, , , , , , .

,

void foo(Object o) {
  if (o instanceof Number) { foo((Number) o); }
  else if (o instanceof String) { foo((String) o); }
}

void foo(String s) { ... }

void foo(Number n) { ... }

{ foo((Object) "foo"); }  // Calls foo(Object) which calls foo(String).
{ foo("foo"); }  // Calls foo(String) without first calling foo(Object).
+5

, . , , .. .

+5

, Server foo bar, Server, Runner.

, delegate . delegate(Runner) Server.

Note that this definition is not executed at run time, it will also contain static analysis of the source code. You just remember that the server was Serverwhat confused you. If you analyze the code without this additional knowledge outside the scope, then you will see what delegate(Runner)really is the only valid choice.

+1
source

All Articles