В чем разница между динамическим и статическим полиморфизмом в Java?

118

Может ли кто-нибудь предоставить простой пример, объясняющий разницу между динамическим и статическим полиморфизмом в Java?

Прабхакар Мантена
источник
4
Переопределения иногда называют «статическим полиморфизмом». Это немного растягивает, но это то, что происходит.
dasblinkenlight
@dasblinkenlight спасибо за информацию. есть ли какой-нибудь пример ??
Прабхакар Мантена
Найдите «перегрузка метода» и «переопределение метода».
dasblinkenlight
5
Я не понимаю, что такое полиморфизм. Полиморфизм - это понятие объекта. мы должны иметь возможность показать объект B как объект A. снизу (ответ). Пример: вы показали собаку как животное, и, следовательно, это полиморфизм. Но при перегрузке вы вызываете другой метод, но с «тем же именем». Как это может быть полиморфизм. Следовательно, «статическое связывание» - это правильный термин, но статический полиморфизм - не в случае перегрузки.
Пунит Радж
@PunithRaj Вы, вероятно, имеете в виду полиморфизм подтипа . Есть еще один вид, называемый Ad hoc, который применяется к перегрузке.
Кельвин

Ответы:

196

Полиморфизм

1. Статическое связывание / связывание во время компиляции / раннее связывание / перегрузка метода (в том же классе)

2. Динамическая привязка / привязка во время выполнения / поздняя привязка / переопределение метода (в разных классах)

пример перегрузки:

class Calculation {  
  void sum(int a,int b){System.out.println(a+b);}  
  void sum(int a,int b,int c){System.out.println(a+b+c);}  

  public static void main(String args[]) {  
    Calculation obj=new Calculation();  
    obj.sum(10,10,10);  // 30
    obj.sum(20,20);     //40 
  }  
}  

преобладающий пример:

class Animal {    
   public void move(){
      System.out.println("Animals can move");
   }
}

class Dog extends Animal {

   public void move() {
      System.out.println("Dogs can walk and run");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal a = new Animal(); // Animal reference and object
      Animal b = new Dog(); // Animal reference but Dog object

      a.move();//output: Animals can move

      b.move();//output:Dogs can walk and run
   }
}
Хан СаАб
источник
6
Я новичок в Java, так что просто любопытно, в чем заключается основная концепция Animal reference but Dog object, почему мы не можем использовать Dog reference and dog object?
pratyay
3
В приведенном выше примере я попытался показать концепцию полиморфизма. мы можем создать ссылку и объект того же класса, но не можем добиться переопределения метода. пожалуйста, прочтите сообщение ниже: stackoverflow.com/questions/12159601/…
KhAn SaAb
перегрузка метода - это полиморфизм времени компиляции. так же. Перегрузка конструктора также является полиморфизмом времени компиляции?
Гаали Прабхакар
29
  • Перегрузка метода была бы примером статического полиморфизма

  • тогда как переопределение было бы примером динамического полиморфизма.

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

user1374
источник
17

Динамический (во время выполнения) полиморфизм - это полиморфизм, существующий во время выполнения. Здесь компилятор Java не понимает, какой метод вызывается во время компиляции. Только JVM решает, какой метод вызывается во время выполнения. Перегрузка метода и переопределение метода с использованием методов экземпляра являются примерами динамического полиморфизма.

Например,

  • Рассмотрим приложение, которое сериализует и десериализует различные типы документов.

  • У нас может быть «Документ» в качестве базового класса и производные от него классы различных типов документов. Например, XMLDocument, WordDocument и т. Д.

  • Класс документа будет определять методы «Serialize ()» и «De-serialize ()» как виртуальные, и каждый производный класс будет реализовывать эти методы по-своему на основе фактического содержимого документов.

  • Когда различные типы документов необходимо сериализовать / десериализовать, на объекты документа будет ссылаться ссылка на класс (или указатель) «Документ», а при вызове метода «Serialize ()» или «De-serialize ()» на нем вызываются соответствующие версии виртуальных методов.

Статический (во время компиляции) полиморфизм - это полиморфизм, проявляемый во время компиляции. Здесь компилятор Java знает, какой метод вызывается. Перегрузка методов и переопределение методов с использованием статических методов; переопределение метода с использованием частных или конечных методов являются примерами статического полиморфизма

Например,

  • У объекта сотрудника может быть два метода print (): один не принимает аргументов, а другой принимает строку префикса, которая будет отображаться вместе с данными сотрудника.

  • С учетом этих интерфейсов, когда метод print () вызывается без каких-либо аргументов, компилятор, глядя на аргументы функции, знает, какая функция должна быть вызвана, и соответственно генерирует объектный код.

Для более подробной информации прочтите «Что такое полиморфизм» (Google it).

rachana
источник
2
Этот ответ полон ошибок: (1) Перегрузка метода не является динамическим полиморфизмом. Это статический полиморфизм. (2) Статические методы никогда не переопределяются, они скрыты / затенены. (3) Частные методы не «переопределяются». Они никогда не передаются по наследству.
Джон Ред
15

Связывание относится к связи между вызовом метода и определением метода.

На этой картинке хорошо видно, что является обязательным.

переплет

На этом рисунке вызов «a1.methodOne ()» привязан к соответствующему определению methodOne (), а вызов «a1.methodTwo ()» привязан к соответствующему определению methodTwo ().

Для каждого вызова метода должно быть правильное определение метода. Это правило в java. Если компилятор не видит правильного определения метода для каждого вызова метода, он выдает ошибку.

Теперь перейдем к статической привязке и динамической привязке в java.

Статическая привязка в Java:

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

,

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

введите описание изображения здесь

На этом рисунке 'a1' - это ссылочная переменная типа Class A, указывающая на объект класса A. 'a2' также ссылочная переменная типа класса A, но указывающая на объект класса B.

Во время компиляции при связывании компилятор не проверяет тип объекта, на который указывает конкретная ссылочная переменная. Он просто проверяет тип ссылочной переменной, через которую вызывается метод, и проверяет, существует ли определение метода для него в этом типе.

Например, для вызова метода «a1.method ()» на изображении выше компилятор проверяет, существует ли определение метода для method () в классе A. Поскольку «a1» является типом класса A. Аналогично, для вызова метода «a2.method ()» он проверяет, существует ли определение метода для method () в классе A. Поскольку «a2» также является типом класса A. Он не проверяет, на какой объект указывают «a1» и «a2». Этот тип привязки называется статической привязкой.

Динамическое связывание в Java:

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

Во время выполнения для привязки используются реальные объекты. Например, для вызова «a1.method ()» на рисунке выше будет вызван метод () фактического объекта, на который указывает «a1». Для вызова «a2.method ()» будет вызван метод () фактического объекта, на который указывает «a2». Этот тип привязки называется динамической привязкой.

Динамическое связывание приведенного выше примера можно продемонстрировать, как показано ниже.

введите описание изображения здесь

Ссылка на статическую привязку и динамическую привязку в java

Эльсайед
источник
лучше, чем раньше.
AnBisw
8

Полиморфизм: полиморфизм - это способность объекта принимать разные формы. Наиболее распространенное использование полиморфизма в ООП происходит, когда ссылка на родительский класс используется для ссылки на объект дочернего класса.

Динамическое связывание / полиморфизм времени выполнения:

Полиморфизм времени выполнения, также известный как переопределение метода. В этом механизме вызов переопределенной функции разрешается во время выполнения.

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");
    }
}

Вывод:

Метод внутреннего старта автомобиля

Статическое связывание / полиморфизм времени компиляции:

Решение о том, какой метод вызывать, решается только во время компиляции.

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;
    }

}

Вывод: метод сортировки внутри коллекции

Loknath
источник
8

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

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

Суджит PS
источник
* (объект создается во время выполнения и переходит в кучу), он должен работать во время выполнения
Встречайте
7

Проще говоря:

Статический полиморфизм : одно и то же имя метода перегружено с другим типом или количеством параметров в одном классе (разные сигнатуры). Целевой вызов метода разрешается во время компиляции.

Динамический полиморфизм : один и тот же метод переопределяется одинаковой сигнатурой в разных классах. . Тип объекта, для которого вызывается метод, неизвестен во время компиляции, но будет определен во время выполнения.

Обычно перегрузка не рассматривается как полиморфизм.

Со страницы руководства по Java :

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

Равиндра бабу
источник
Generally overloading won't be considered as polymorphism.не могли бы вы уточнить этот момент.
премьер
1
Динамическое связывание и переопределение - поразительный момент для полиморфизма
Равиндра бабу
5

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

И методы Перекрытие известно как Dynamic полиморфизм или просто полиморфизм или время выполнения метод отправка или динамическое связывание , поскольку переопределяется метод вызов разрешаются во время выполнения.

Чтобы понять, почему это так, давайте возьмем пример Mammalи Humanкласс

class Mammal {
    public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}

class Human extends Mammal {

    @Override
    public void speak() { System.out.println("Hello"); }

    public void speak(String language) {
        if (language.equals("Hindi")) System.out.println("Namaste");
        else System.out.println("Hello");
    }

}

Я включил вывод, а также байт-код в следующие строки кода

Mammal anyMammal = new Mammal();
anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V

И, посмотрев на приведенный выше код, мы видим, что байт-коды humanMammal.speak (), human.speak () и human.speak («хинди») совершенно разные, потому что компилятор может различать их на основе списка аргументов. и ссылка на класс. Вот почему перегрузка метода известна как статический полиморфизм. .

Но байт-код для anyMammal.speak () и humanMammal.speak () такой же, потому что в соответствии с компилятором оба метода вызываются по ссылке Mammal, но вывод для обоих вызовов методов отличается, потому что во время выполнения JVM знает, какой объект удерживает ссылка, и вызывает JVM метод объекта, поэтому переопределение метода известно как динамический полиморфизм.

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

Если вы хотите узнать больше об этом, вы можете прочитать больше о том, как JVM обрабатывает перегрузку и переопределение методов внутренне .

Нареш Джоши
источник
3

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

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

Kulasangar
источник
3

Полиморфизм относится к способности объекта вести себя по-разному для одного и того же триггера.

Статический полиморфизм (полиморфизм времени компиляции)

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

Динамический полиморфизм (полиморфизм времени выполнения)

  • Динамический полиморфизм решает, какой метод выполнять во время выполнения.
  • Переопределение метода - это пример динамического полиморфизма, и требуется, чтобы он происходил динамический полиморфизм.
  • Динамический полиморфизм достигается за счет динамического связывания.
  • Динамический полиморфизм происходит между разными классами.
  • Это требуется, когда объект подкласса назначается объекту суперкласса для динамического полиморфизма.
  • Наследование используется для динамического полиморфизма.
Савендра Эканаяке
источник
1

Полиморфизм времени компиляции (статическое связывание / раннее связывание): в статическом полиморфизме, если мы вызываем метод в нашем коде, то определение того, какое определение этого метода должно быть вызвано на самом деле, разрешается только во время компиляции.

(или)

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

Динамический полиморфизм (полиморфизм позднего связывания / времени выполнения): во время выполнения Java ожидает, пока среда выполнения не определит, на какой объект фактически указывает ссылка. Разрешение метода было принято во время выполнения, поэтому мы называем это полиморфизмом времени выполнения.

Паван Редди
источник
1

Рассмотрим код ниже:

public class X
{
    public void methodA() // Base class method
    {
        System.out.println ("hello, I'm methodA of class X");
    }
}

public class Y extends X
{
    public void methodA() // Derived Class method
    {
        System.out.println ("hello, I'm methodA of class Y");
    }
}
public class Z
{
public static void main (String args []) {

    //this takes input from the user during runtime
    System.out.println("Enter x or y");
    Scanner scanner = new Scanner(System.in);
    String value= scanner.nextLine();

    X obj1 = null;
    if(value.equals("x"))
        obj1 = new X(); // Reference and object X
    else if(value.equals("y"))
        obj2 = new Y(); // X reference but Y object
    else
        System.out.println("Invalid param value");

    obj1.methodA();
}
}

Теперь, глядя на код, вы никогда не сможете сказать, какая реализация methodA () будет выполнена, потому что это зависит от того, какое значение пользователь задает во время выполнения. Таким образом, только во время выполнения решается, какой метод будет вызван. Следовательно, полиморфизм времени выполнения.

user2048204
источник
0

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

class Person                                            //person.java file
{
    public static void main ( String[] args )
    {
      Eat e = new Eat();
       e.eat(noodle);                                //line 6
    }

   void eat (Noodles n)      //Noodles is a object    line 8                     
   {

   }
   void eat ( Pizza p)           //Pizza is a object
  {

  }

}

В этом примере у Person есть метод eat, который означает, что он может съесть пиццу или лапшу. Что метод eat перегружен, когда мы компилируем этот Person.java, компилятор разрешает вызов метода "e.eat (noodles) [который находится в строке 6] с определением метода, указанным в строке 8, то есть это метод, который принимает лапшу в качестве параметра и весь процесс выполняется компилятором, поэтому это полиморфизм времени компиляции.Процесс замены вызова метода определением метода называется связыванием, в этом случае это выполняется компилятором, поэтому он вызывается как раннее связывание.

Манодж Гурурадж
источник
0

Следуя ответу Нареша, динамический полиморфизм является только «динамическим» в Java из-за наличия виртуальной машины и ее способности интерпретировать код во время выполнения, а не код, выполняющийся изначально.

В C ++ это должно быть разрешено во время компиляции, если он компилируется в собственный двоичный файл с использованием gcc, очевидно; однако скачки и переходы во время выполнения в виртуальной таблице по-прежнему называются «поисковыми» или «динамическими». Если C наследует B, и вы объявляете , c уже будет указывать на внешний объект C, и указатель будет передан в C :: method1 () в текстовом сегменте. См .: http://www.programmersought.com/article/2572545946/B* b = new C(); b->method1(); , компилятор разрешит b, чтобы указать на объект B внутри C (для простого класса наследует ситуацию класса, объект B внутри C и C будет начинаться с того же адреса памяти, поэтому ничего необходимо сделать; он будет указывать на vptr, который они оба используют). Если C наследует B и A, таблица виртуальных функций объекта A внутри записи C для метода1 будет иметь преобразователь, который смещает указатель на начало инкапсулирующего объекта C, а затем передает его в реальный A :: method1 () в текстовом сегменте, который C переопределил. ДляC* c = new C(); c->method1()

В java для B b = new C(); b.method1();виртуальная машина может динамически проверять тип объекта в паре с b, передавать правильный указатель и вызывать правильный метод. Дополнительный шаг виртуальной машины устраняет необходимость в таблицах виртуальных функций или типе, определяемом во время компиляции, даже если он может быть известен во время компиляции. Это просто другой способ сделать это, который имеет смысл, когда задействована виртуальная машина, а код компилируется только в байт-код.

Льюис Келси
источник