Верно ли сказать, что каждая привязка времени выполнения была статической привязкой во время компиляции?

Я очень запутался в привязке к теме. Как мы знаем, в статической привязке для определения привязки проверяется тип ссылки, а не объект, на который она ссылается, а при динамической привязке принимается во внимание тип объекта, на который указывает ссылка.

class A
{
    void show()
    {
        System.out.println("From A");
    }
}
class B extends A
{
    void show()
    {
        System.out.println("From B");
    }
}
class Main
{
    public static void main(String[] quora)
    {
        A a1 = new A();
        A a2 = new B();

        a1.show(); //line 1
        a2.show(); //line 2
    }
}

В приведенном выше примере мы видим, что во время компиляции и Line1, и line2 будут обрабатываться статической привязкой, и они будут ссылаться на метод show A-класса (поскольку тип ссылки - A). Но во время выполнения вызов разрешается, и line1 ссылается на метод A-класса show (), а line2 ссылается на метод B-класса, то есть на тип объекта или, можно сказать, динамическое связывание.

Итак, мое главное намерение - узнать следующее.

  1. Всегда ли динамическое связывание возникает после статического связывания? или я что то не так понимаю?

  2. Если это правда, то правда ли, что каждый метод динамически связан во время выполнения?

  3. Можем ли мы это обобщить?


person pyskmr    schedule 01.10.2019    source источник
comment
Можем ли мы обобщить что?   -  person Sweeper    schedule 01.10.2019
comment
что бы ни случилось, всегда будет статическая привязка, а затем динамическая привязка для каждого вызова метода. @Sweeper   -  person pyskmr    schedule 01.10.2019
comment
Это правда, но я все еще не понимаю вашего второго вопроса.   -  person Sweeper    schedule 01.10.2019
comment
Я обновил то же самое, для облегчения понимания @Sweeper   -  person pyskmr    schedule 01.10.2019


Ответы (1)


По сути, каждый раз, когда вы вызываете метод, компилятор должен выяснить, какую перегрузку вызывать, в зависимости от типов и аргументов, которые вы передаете методу. Это статическая привязка. Затем во время выполнения среда выполнения определит, какую реализацию перегрузки (которая уже решена на данный момент) вызывать.

Учитывать:

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.

Всегда ли динамическое связывание возникает после статического связывания?

Как видно из результатов приведенного выше кода, ответ положительный. Статическое связывание происходит во время компиляции, динамическое связывание происходит во время выполнения, поэтому первое всегда происходит первым.

Если это правда, то правда ли, что каждый метод динамически связан во время выполнения?

Я не уверен, что вы имеете в виду, поэтому, надеюсь, подробное объяснение, приведенное выше, уже дало бы ответ на этот вопрос.

несмотря ни на что, всегда будет статическая привязка, а затем динамическая привязка для каждого вызова метода?

Да, но иногда эти два процесса могут происходить очень быстро, потому что вариантов очень мало. Вам, вероятно, не нужно делать «выбор» в динамической привязке, когда класс, для которого вы вызываете метод, является последним классом, не так ли?

person Sweeper    schedule 01.10.2019
comment
Правильно ли будет сказать, что статическая привязка - это скорее проверка, тогда как динамическая привязка - это настоящая привязка? Потому что на самом деле привязки не будет, если не будет создан какой-либо объект, а объект всегда создается во время выполнения. Я прав, @Sweeper? - person pyskmr; 01.10.2019
comment
@pyskmr Ну, статическая привязка все еще влияет на то, какой метод вызывается. Если все будет сделано во время выполнения, то в моем примере было бы напечатано From B (String). Так что это не просто чек. - person Sweeper; 01.10.2019
comment
И в final классе, поскольку класс final, поэтому он не будет унаследован никаким классом, поэтому не будет никакого выбора во время выполнения (поскольку не будет никакого переопределенного метода final class method) он вызовет только соответствующий метод. правильно? - person pyskmr; 01.10.2019
comment
@pyskmr класс, который является окончательным во время компиляции, не обязательно должен быть окончательным во время выполнения. Кроме того, метод, вызываемый в конечном классе, может оказаться унаследованным методом. Поэтому неправильно говорить, что во время выполнения нет выбора. Единственное, что можно сказать, это то, что для вызова последнего типа получателя цель никогда не изменится после разрешения. - person Holger; 05.02.2020