В чем разница между привязкой и отправкой в ​​Java?

Слишком много связанных имен: раннее и позднее связывание, статическая и динамическая отправка, время выполнения и полиморфизм времени компиляции и т. д., что я не понимаю разницы.

Я нашел четкое объяснение, но правильно ли оно ? Я перефразирую JustinC:

Привязка: определяет тип переменной (объекта?). Если это делается во время компиляции, это раннее связывание. Если это делается во время выполнения, это позднее связывание.

Отправка: определяет, какой метод соответствует вызову метода. Статическая диспетчеризация вычисляет методы во время компиляции, тогда как динамическая диспетчеризация делает это во время выполнения.

Сопоставляет ли Binding примитивные и ссылочные переменные с примитивными значениями и объектами соответственно?

Редактировать: пожалуйста, дайте мне четкий справочный материал, чтобы я мог больше узнать об этом.


person Code_Steel    schedule 07.01.2017    source источник
comment
проверьте также stackoverflow.com/questions/20187587/.   -  person Roberto Attias    schedule 07.01.2017


Ответы (3)


Я считаю, что путаница обычно возникает из-за того, насколько перегружены эти термины.

Мы программируем наши программы на языке высокого уровня, и либо компилятор, либо интерпретатор должен преобразовать это во что-то, что машина действительно понимает.

Грубо говоря, вы можете представить компилятор, преобразующий код нашего метода в некую форму машинного кода. Если бы компилятор точно знал в этот момент, где именно в памяти будет находиться этот метод, когда мы позже запустим нашу программу, то он мог бы безопасно найти каждый вызов метода этого скомпилированного метода и заменить его переходом на этот адрес, где находится скомпилированный код. проживает, верно?.

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

Термины «статический» и «динамический» обычно используются для обозначения объектов, привязанных до выполнения и во время выполнения соответственно.

Более позднее время связывания связано с большей гибкостью, более раннее время связывания связано с большей эффективностью. Разработчики языков должны сбалансировать эти два аспекта при создании языка.

Большинство объектно-ориентированных языков программирования поддерживают полиморфизм подтипов. В этих языках виртуальные методы привязываются во время выполнения в зависимости от динамического типа объекта в этот момент. Другими словами, вызовы виртуальных методов направляются в соответствующую реализацию во время выполнения на основе динамического типа задействованной реализации объекта, а не исключительно на его статической ссылке на тип.

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

Я отвечал на очень похожий вопрос в прошлом, в котором я демонстрирую на примерах, как это происходит в Java.

Я бы также рекомендовал прочитать книгу Прагматика языка программирования . Это отличная ссылка для изучения всего этого с теоретической точки зрения.

person Edwin Dalorzo    schedule 07.01.2017

Когда вы ищете определения «низкого уровня», вероятно, единственным законным источником является наш старый друг — JLS. Хотя в данном случае он не дает четкого определения, контекста, в котором используется каждый термин, может быть достаточно.

Отправлять

Этот термин действительно упоминается в процедурах определения того, какой метод вызывать.

15.12.2. Шаг 2 во время компиляции: определение подписи метода

На втором этапе выполняется поиск методов-членов в типе, определенном на предыдущем шаге. На этом шаге имя метода и выражения аргументов используются для поиска методов, которые являются как доступными, так и применимыми, то есть объявлениями, которые могут быть правильно вызваны для заданных аргументов.

Таких методов может быть несколько, и в этом случае выбирается наиболее конкретный. Дескриптор (сигнатура плюс тип возвращаемого значения) наиболее конкретного метода — это тот, который используется во время выполнения для выполнения отправки метода. Метод применим, если он применим одним из строгих вызовов

Подробная информация о том, какой метод является «наиболее конкретным», приведена в разделе 15.12.2.5 «Выбор наиболее конкретного метода».

Что касается "динамической отправки",

JLS 12.5. Создание новых экземпляров класса:

В отличие от C++, язык программирования Java не определяет измененных правил диспетчеризации методов при создании нового экземпляра класса. Если вызываются методы, которые переопределяются в подклассах инициализируемого объекта, то эти переопределяющие методы используются даже до того, как новый объект будет полностью инициализирован.

Оно включает

Пример 12.5-2. Динамическая отправка во время создания экземпляра

class Super {

  Super() {
      printThree();
  }

  void printThree() {
      System.out.println("three");
  }
}

class Test extends Super {

  int three = 3;

  void printThree() {
      System.out.println(three);
  }

  public static void main(String[] args) {
      Test t = new Test();
      t.printThree();
  }
}

Выход:

0
3

Это происходит потому, что во время цепочки вызовов конструктора конструктор Super вызывает printThree, но из-за динамической диспетчеризации вызывается метод в Test, и это происходит до инициализации поля.

Связывание

Этот термин используется в контексте доступа к членам класса.

Пример 15.11.1-1. Статическая привязка для доступа к полям демонстрирует раннее и позднее связывание. Обобщу приведенные там примеры для ленивых из нас:

class S {
    int x = 0;
    int z() { return x; }
}

class T extends S {
    int x = 1;
    int z() { return x; }
}

public class Test1 {

    public static void main(String[] args) {
        S s = new T();
        System.out.println("s.x=" + s.x);
        System.out.println("s.x=" + s.z());
    }
}

Выход:

s.x=0
s.x=1

Показано, что поле использует «раннее связывание», а метод экземпляра использует «позднее связывание»:

Это отсутствие динамического поиска для доступа к полям позволяет эффективно запускать программы с помощью простых реализаций. Возможности позднего связывания и переопределения доступны, но только при использовании методов экземпляра.

Связывание также используется для определения типа универсального,

8. Классы

Классы могут быть универсальными (§8.1.2), то есть они могут объявлять переменные типа, привязки которых могут различаться в разных экземплярах класса.

Это означает, что если вы создадите 2 экземпляра List<String>, привязки String в обоих экземплярах будут отличаться друг от друга.

Это также относится к необработанным типам:

4.8. Необработанные типы

class Outer<T>{
    T t;
    class Inner {
        T setOuterT(T t1) { t = t1; return t; }
    }
}

Тип членов Inner зависит от параметра типа Outer. Если Outer является необработанным, Inner также должен рассматриваться как необработанный, поскольку для T нет допустимой привязки.

Это означает, что объявление Outer outer (это вызовет предупреждение о необработанном типе) не позволяет определить тип T (очевидно - он не был определен в объявлении).

person user1803551    schedule 07.01.2017

Это общие термины, вы можете обобщить их следующим образом: когда какая-то вещь (метод или объект) является статической/ранней, это означает, что эта вещь настроена во время компиляции, и во время выполнения нет двусмысленности, например, в следующем коде:

class A {
    void methodX() {
    System.out.print("i am A");
    }
 }

Если мы создадим экземпляр A и вызовем методX(), ничего сложного и все будет настроено во время компиляции, но если у нас есть следующий код

class B extends A {
  void methodX() {
    System.out.print("i am B");
   }
 }
....
A objX= new B();
objX.methodX();

Результат метода x неизвестен до времени выполнения, поэтому этот метод динамически связывается/отправляется (мы можем использовать термин диспетчеризированный вместо связывания для методов ссылка).

person Mr.Q    schedule 07.01.2017
comment
Вы объяснили метод диспетчеризации. Что насчет привязки? Это тесно связанный термин, но отдельное понятие. - person Code_Steel; 07.01.2017