По сути, каждый раз, когда вы вызываете метод, компилятор должен выяснить, какую перегрузку вызвать, основываясь на типах и аргументах, которые вы передаете методу. Это статическая привязка. Затем во время выполнения среда выполнения выяснит, какую реализацию перегрузки (которая уже решена на этом этапе) вызвать.
Рассмотрим:
class A
{
void f(Object o)
{
System.out.println("From A");
}
}
class B extends A
{
void f(Object o)
{
System.out.println("From B (Object)");
}
void f(String s)
{
System.out.println("From B (String)");
}
}
Ивы делаете:
A a = new B();
a.f("");
Что происходит? Во время компиляции компилятор выбрал перегрузку f(Object)
из-за типа a
, являющегося A
(есть только один метод на выбор!). Затем во время выполнения, поскольку a
фактически ссылается на экземпляр B
, вызывается реализация B
перегрузки f(Object)
, выводя From B (Object)
. Одно заблуждение, которое я видел, - ожидать, что результат будет From B (String)
. Это неправильно, потому что компилятор не знает о существовании этой перегрузки на a
.
Всегда ли динамическое связывание всегда происходит после статического связывания?
Как мыКак видно из результатов приведенного выше кода, ответ - да. Статическое связывание происходит во время компиляции, динамическое связывание происходит во время выполнения, поэтому первое всегда происходит первым.
Если это правда, то правда ли, что каждый метод динамически связан во время выполнения?
Я не уверен, что вы подразумеваете под этим, так что, надеюсь, подробное объяснение выше уже ответило бы на это.
несмотря ни на что, всегда будет статическое связывание итогда динамическое связывание для каждого вызова метода?
Да, но иногда эти два процесса могут идти очень быстро, потому что вариантов очень мало. Вам, вероятно, не нужно делать «выбор» в динамическом связывании, когда класс, для которого вы вызываете метод, является конечным классом, не так ли?