Статическая и динамическая привязка в Java
в настоящее время я выполняю задание для одного из моих классов, и в нем я должен привести примеры, используя синтаксис Java, из статический и динамическое связывание.
Я понимаю основную концепцию, что статическая привязка происходит во время компиляции, а динамическая привязка происходит во время выполнения, но я не могу понять, как они на самом деле работают конкретно.
Я нашел пример статической привязки в интернете, который дает этот пример:
public static void callEat(Animal animal) {
System.out.println("Animal is eating");
}
public static void callEat(Dog dog) {
System.out.println("Dog is eating");
}
public static void main(String args[])
{
Animal a = new Dog();
callEat(a);
}
и что это будет печатать "животное ест", потому что вызов callEat
использует статическое связывание, но я не уверен, что почему это считается статической привязкой.
до сих пор ни один из источников, которые я видел, не смог объяснить это таким образом, что я могу следовать.
6 ответов:
С Javarevisited сообщение в блоге:
вот несколько важных различий между статической и динамической привязкой:
- статическая привязка в Java происходит во время компиляции, а динамическая привязка происходит во время выполнения.
private
,final
иstatic
методы и переменные используют статическую привязку и связаны компилятором, в то время как виртуальные методы связаны во время выполнения на основе объекта времени выполнения.- статическая привязка использует
Type
(class
в Java) информация для привязки, в то время как динамическая привязка использует объект для разрешения привязки.- перегруженные методы связаны с использованием статической привязки, а переопределенные методы связаны с использованием динамической привязки во время выполнения.
вот пример, который поможет вам понять как статическое, так и динамическое связывание в Java.
пример статической привязки в Java
public class StaticBindingTest { public static void main(String args[]) { Collection c = new HashSet(); StaticBindingTest et = new StaticBindingTest(); et.sort(c); } //overloaded method takes Collection argument public Collection sort(Collection c) { System.out.println("Inside Collection sort method"); return c; } //another overloaded method which takes HashSet argument which is sub class public Collection sort(HashSet hs) { System.out.println("Inside HashSet sort method"); return hs; } }
выход: метод сортировки внутри коллекции
пример динамической привязки в Java
public class DynamicBindingTest { public static void main(String args[]) { Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car vehicle.start(); //Car's start called because start() is overridden method } } class Vehicle { public void start() { System.out.println("Inside start method of Vehicle"); } } class Car extends Vehicle { @Override public void start() { System.out.println("Inside start method of Car"); } }
выход: внутренний метод запуска автомобиля
подключение вызова метода к телу метода называется привязкой. Как сказал Маулик " статическая привязка использует информацию типа (класса в Java) для привязки, а динамическая привязка использует объект для разрешения привязки."Итак, этот код:
public class Animal { void eat() { System.out.println("animal is eating..."); } } class Dog extends Animal { public static void main(String args[]) { Animal a = new Dog(); a.eat(); // prints >> dog is eating... } @Override void eat() { System.out.println("dog is eating..."); } }
даст результат:собака ест... потому что он использует ссылку на объект, чтобы найти, какой метод использовать. Если мы изменим приведенный выше код на этот:
class Animal { static void eat() { System.out.println("animal is eating..."); } } class Dog extends Animal { public static void main(String args[]) { Animal a = new Dog(); a.eat(); // prints >> animal is eating... } static void eat() { System.out.println("dog is eating..."); } }
Она будет производить : животное ест... поскольку это статический метод, поэтому он использует тип (в данном случае животное), чтобы решить, какой статический метод вызывать. Кроме статических методов частные и конечные методы используют тот же подход.
компилятор знает только, что тип "а"
Animal
; это происходит во время компиляции, из-за чего он называется статической привязкой (перегрузка метода). Но если это динамическая привязка, то он будет вызыватьDog
метод класса. Вот пример динамической привязки.public class DynamicBindingTest { public static void main(String args[]) { Animal a= new Dog(); //here Type is Animal but object will be Dog a.eat(); //Dog's eat called because eat() is overridden method } } class Animal { public void eat() { System.out.println("Inside eat method of Animal"); } } class Dog extends Animal { @Override public void eat() { System.out.println("Inside eat method of Dog"); } }
выход: Внутри есть метод собаки
есть три основных различия между статической и динамической привязкой при проектировании компиляторов и как переменные и процедуры переданы runtime окружающая среда. Эти различия заключаются в следующем:
Статическое Связывание: в статической привязке обсуждаются три следующие проблемы:
определение процедуры
объявление a имя (переменная и др.)
объем декларации
Динамическое Связывание: три проблемы, которые встречаются в динамической привязке, следующие:
активация процедуры
привязка имени
время жизни привязки
со статическим методом в Родительском и дочернем классе: статическая привязка
public class test1 { public static void main(String args[]) { parent pc = new child(); pc.start(); } } class parent { static public void start() { System.out.println("Inside start method of parent"); } } class child extends parent { static public void start() { System.out.println("Inside start method of child"); } } // Output => Inside start method of parent
Динамическое Связывание :
public class test1 { public static void main(String args[]) { parent pc = new child(); pc.start(); } } class parent { public void start() { System.out.println("Inside start method of parent"); } } class child extends parent { public void start() { System.out.println("Inside start method of child"); } } // Output => Inside start method of child
потому что компилятор знает, что связывание во время компиляции. Например, если вы вызываете метод на интерфейсе, то компилятор не может знать, и привязка разрешена во время выполнения, потому что фактический объект, имеющий метод, вызванный на нем, может быть одним из нескольких. Поэтому это время выполнения или динамическая привязка.
ваш вызов привязан к классу Animal во время компиляции, потому что вы указали тип. Если вы передали эту переменную в другой метод где-то в противном случае никто не знал бы (кроме вас, потому что вы написали это), какой фактический класс это будет. Единственная подсказка-это объявленный тип животного.