2015-01-29 3 views
2

Ниже приведен пример кодаРазъяснение в справочной переменной понижающее приведение в Java

class Animal { 
    void makeNoise() {System.out.println("generic noise"); } 
} 

class Dog extends Animal { 
    void makeNoise() {System.out.println("bark"); } 
    void playDead() { System.out.println("roll over"); } 
} 

class DogTest { 
    public static void main(String [] args) { 
     Animal animal = new Animal(); 
     Dog d = (Dog) animal; 
     d.makeNoise(); 
    } 
} 

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

java.lang.ClassCastException

Мое предположение заключается в том, что он должен печатать «общий шум», потому что во время выполнения он должен вызывать действительный метод makeNoise() объекта Animal без каких-либо исключений.

ответ

3

Все ответы здесь технически правильные. Но я хочу объяснить это с другой точки зрения.

Прежде всего, вы определили один Animal и один Dog. Пока все в порядке. Проблема возникает, когда вы (в пределах DogTest) создаете Animal и литой ти как Dog. Зачем? Не каждый Animal является Dog. Я имею в виду, что Animal может быть Bird, a Cat, Elephant ... Эти Animal s не «лают».Сказал, что вы можете сделать как животное, потому что все Dog s - Animal s.

Я надеюсь, что прояснили немного ваш ум :)

+0

У меня есть ваше мнение. благодаря –

0

Это ничего не печатает, потому что вы не достигнете линии d.makeNoise(). java.lang.ClassCastException забрасывается в более раннюю строку, когда вы пытаетесь сделать Dog что-то, что не является Dog.

Тем не менее, без этой строки вы получите ожидаемый результат: «общий шум».

4

Вы не можете бросить произвольный Animal экземпляр к Dog, например, если экземпляр вы литья не является на самом деле Dog или подклассу Dog.

Было бы больше смысла для Animal класс абстрактным, так как фактические животных, которые могут быть созданы должно быть специфическим для животных, таких как Dog, Cat и т.д ...

3

Если вы имели:

Animal animal = new Dog(); 
Dog dog = (Dog) animal; 

не было проблем.

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

В вашем коде, однако, тип времени выполнения animal - Animal (то же, что и тип времени компиляции). Это означает, что animal укажет на объект в куче, который поддерживает функции Animal (который равен makeNoise()), но не функции Dog, и именно поэтому происходит ClassCastException.

+1

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

0

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

public interface Animal { 
      public void show(); 
     } 


     public abstract class Dog implements Animal { 

      public void display(){ 
       System.out.println("Dog Called"); 
      } 
     } 

     public class Impl extends Dog{ 

      @Override 
      public void show() { 
       System.out.println("Impl Called"); 
      } 
     } 


      class DogTest { 
      public static void main(String [] args) { 
       Animal a = new Impl(); 
       /** 
       * child class's method tried to be accessed with the help of 
       * parent class's object using downcasting of object 
       * */ 
       ((Dog)a).display(); 
      } 
    } 

Однако в реальном масштабе времени такие требования могут выполняться без используя явное downcasting объектов вместо этого с помощью Factory Design Pattern, в котором мы создаем объект, не подвергая логику создания клиенту и ссылаясь на вновь созданный объект, используя общий интерфейс.

Полная картина завод может быть вытянут из here

Смежные вопросы