Разница между отражением и поздним связыванием в Java с примерами в реальном времени - PullRequest
6 голосов
/ 24 января 2012

Во время изучения учебников по Java Reflection и Late Binding меня смутили.В некоторых уроках они написали, что оба они одинаковы, и что между Reflection и Late Binding нет никакой разницы.Но другие учебники говорят, что есть разница.

Я в замешательстве, поэтому кто-то может объяснить, пожалуйста, что такое Reflection и Late Binding в Java, и, если возможно, приведите несколько реальных примеров того и другого.

Спасибо ..

Ответы [ 5 ]

3 голосов
/ 24 января 2012

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

Возьмем случай N классов, реализующих абстрактный метод интерфейса (или абстрактный класс, fwiw).

public interface IMyInterface {

    public void doSomething();    
}

public class MyClassA implements IMyInterface {

    public void doSomething(){ ... }
}

public class MyClassB implements IMyInterface {

    public void doSomething(){ ... }
}

public class Caller {

    public void doCall(IMyInterface i){
        // which implementation of doSomething is called?
        // it depends on the type of i: this is late binding
        i.doSomething(); 
    }
}

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

Здесь очень хорошее объяснение отражения: Что такое отражение и почему оно полезно?

3 голосов
/ 24 января 2012

Позднее связывание (также известное как динамическая диспетчеризация) не нуждается в отражении - ему все еще нужно знать , какой член должен динамически связываться с во время компиляции (т.е. сигнатура элемент известен во время компиляции), хотя привязка к переопределенным элементам происходит во время выполнения.

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

2 голосов
/ 24 января 2012

Примеры из реальной жизни:

Если вы строите свой проект с jdesktop 0.8, но поставляете с jdesktop 0.9, ваш код все равно будет использовать функции 0.9, потому что он использует преимущество позднего связывания, то есть код, который вашКодовые вызовы - это версия, загружаемая загрузчиком классов, независимо от версии, с которой он был скомпилирован.(Это в отличие от компоновщиков, которые встраивают версию вызываемого кода во время компиляции в приложение.)

Для размышления, допустим, вы пытаетесь настроить таргетинг на Java 1.5 и 1.6, но хотите использовать tabкомпоненты в 1.6, если они доступны, то вы проверите их наличие, используя отражение в классе JTabbedPane, чтобы найти метод setTabComponentAt.В этом случае вы работаете с Java 1.5, которая вообще не имеет этих функций, поэтому вы не можете вызвать их напрямую, иначе компиляция не удастся.Однако, если в системе конечного пользователя вы работаете с 1.6 (здесь вступает в силу позднее связывание), вы можете использовать рефлексию для вызова методов, которых не было в 1.5.

Они связаны;многие виды использования рефлексии полагаются на позднее связывание, чтобы быть полезным, но это принципиально разные аспекты языка и его реализации.

1 голос
/ 24 января 2012

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

В следующем коде вы можете динамически создавать новый объект с помощьюотражение (посмотрите, как конструктор извлекается и используется с помощью класса, а не просто с помощью чего-то вроде объекта obj = new MyClass ("MyInstance")).Аналогичным образом можно получить доступ к другим формам конструктора, методам и атрибутам.Для получения дополнительной информации об отражении в посещении Java: http://java.sun.com/developer/technicalArticles/ALT/Reflection/


... in some method of some class ...
Class c = getClass();
Constructor ctor = c.getConstructor( String.class );
Object obj = ctor.newInstance( "MyInstance" );

0 голосов
/ 22 сентября 2017

Я должен не согласиться с большинством ответов здесь -

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

Позднее связывание подразумевает абсолютно отсутствие проверок вызова метода во время компиляции и никаких ошибок компиляции, если метод не существует.

Java, однако, выдаст ошибку компиляции, если метод не существует где-то в иерархии типов типа, квалифицирующего вызов метода (будучи несколько приблизительным при описании поведения здесь).Это не чисто традиционная поздняя привязка.То, что делает Java в обычном не приватном не окончательном вызове статического метода, лучше назвать динамической диспетчеризацией.
Однако, если мы используем отражение в Java, тогда Java выполняет чисто позднюю привязку, поскольку компилятор просто не может проверить, вызывает ли вызываемый методсуществует или нет.Вот пример:

class A
{
    public void foo()
    {
        System.out.println("Foo from A");
    }
}

class B extends A
{
    public void foo()
    {
        System.out.println("Foo from B");
    }
}
public class C
{
   public static void main(String [] args)
    {
         A a=new A();
         B b=new B();
         A ref=null;
         Class ref1 = null;
         ref1 = b.getClass();
         ref.foo1();//will not compile because Java in this normal method
         //call does some compile time checks for method and method 
         //signature existence. NOT late binding in its pure form.
         try {
            ref1.getMethod("foo1").invoke(null); //will throw a 
            //NoSuchMethodException at runtime, but compiles perfectly even 
            //though foo1 does not exist. This is pure late binding.
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
       }
}
...