В чем разница между up-casting и down-casting относительно переменной класса


в чем разница между up-casting и down-casting относительно переменной класса?

например, в следующем классе программы Animal содержит только один метод, но класс Dog содержит два метода, а затем как мы приводим переменную Dog к переменной Animal.

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

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}
9 91

9 ответов:

Upcasting бросает в супертип, а приведения типов кастинг к подтипу. Upcasting всегда разрешен, но downcasting включает проверку типа и может бросить ClassCastException.

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

Downcasting будет что-то вроде этого:

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

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

однако, если вы должны были сделать это:

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

взять ClassCastException. Этот причина почему потому что animal тип времени выполнения Animal, и поэтому, когда вы говорите среде выполнения выполнить приведение он видит, что animal на самом деле это не Dog и так бросает!--3-->.

чтобы вызвать метод суперкласса, вы можете сделать super.method() или выполнив сброс.

чтобы вызвать метод подкласса, вы должны сделать понижение. Как показано выше, вы обычно рискуете ClassCastException при этом, однако, вы можете использовать instanceof оператор для проверки типа времени выполнения объект перед выполнением приведения, что позволяет предотвратить ClassCastExceptions:

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
    // Guaranteed to succeed, barring classloader shenanigans
    Dog castedDog = (Dog) animal;
}

вниз-кастинг и вверх-кастинг был следующим:
enter image description here

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

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

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException

Upcasting и downcasting являются важной частью Java, которая позволяет нам создавать сложные программы с использованием простого синтаксиса и дает нам большие преимущества, такие как полиморфизм или группировка различных объектов. Java позволяет объекту типа подкласса обрабатываться как объект любого типа суперкласса. Это называется upcasting. Upcasting делается автоматически, во время приведения типов должны быть сделано вручную программистом, и я собираюсь дать все возможное, чтобы объяснить почему это так.

Upcasting и downcasting не похожи на кастинг примитивов от одного к другому, и я считаю, что это то, что вызывает много путаницы, когда программист начинает изучать объекты кастинга.

полиморфизм: все методы в Java являются виртуальными по умолчанию. Это означает, что любой метод может быть переопределен при использовании в наследовании, если этот метод не объявлен как final или static.

вы можете увидеть пример ниже как getType(); работает в соответствии с типом объекта (Собака,домашнее животное,полицейская собака).

Предположим, у вас есть три собаки

  1. Собака - это супер класс.
  2. собака - собака выходит Собака.
  3. полицейская собака-полицейская собака расширяет домашнюю собаку.

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }
    

полиморфизм : все методы в Java являются виртуальными по умолчанию. Это означает, что любой метод может быть переопределен при использовании в наследовании, если только этот метод объявлен как Final или static.(Объяснение относится к концепции виртуальных таблиц)

виртуальная таблица / таблица отправки: таблица отправки объекта будет содержать адреса динамически связанных методов объекта. Вызовы метода выполняются путем извлечения адреса метода из таблицы диспетчеризации объекта. Таблица диспетчеризации одинакова для всех объектов, принадлежащих к одному классу, и поэтому обычно используется совместно их.

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

печать Normal Dog

  obj2.getType();

печать Pet Dog

 obj3.getType();

печать Police Dog

Downcasting нужно сделать программистом вручную

при попытке вызвать secretID(); метод on obj3 что это PoliceDog object но ссылаться на Dog который является суперклассом в иерархии он выдает ошибку, так как obj3 не имеют доступа к secretId() метод. In чтобы вызвать этот метод, вам нужно вручную понизить этот obj3 доPoliceDog

  ( (PoliceDog)obj3).secretID();

, который печатает ID

аналогичным образом вызвать dogName();метод PetDog класс вам нужно опустить obj2 до PetDog так как obj2 ссылается на Dog и не имеют доступа к dogName(); метод

  ( (PetDog)obj2).dogName();

почему это так, что upcasting является автоматическим, но downcasting должен быть ручным? Ну, вы видите, upcasting может никогда не подведет. Но если у вас есть группа разных собак и вы хотите опустить их всех до их типов, то есть шанс, что некоторые из этих собак на самом деле разных типов, т. е. PetDog,PoliceDog, и процесс терпит неудачу, бросая ClassCastException.

это причина, по которой вам нужно опустите свои объекты вручную если вы ссылались на свои объекты к типу суперкласса.

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

Я знаю, что этот вопрос задан довольно давно, но для новых пользователей этого вопроса. Пожалуйста, прочитайте эту статью, где содержится полное описание на upcasting, downcasting и использование instanceof оператор

  • нет необходимости поднимать вручную, это происходит само по себе:

    Mammal m = (Mammal)new Cat(); равна Mammal m = new Cat();

  • но понижение всегда должно быть сделано вручную:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat
    

Почему это так, что upcasting является автоматическим, но downcasting должен быть ручным? Ну, вы видите, апкастинг никогда не может потерпеть неудачу. Но если у вас есть группа разных животных и вы хотите опустить их всех на кошку, то есть шанс, что некоторые из этих животных на самом деле собаки, и процесс терпит неудачу, бросая ClassCastException. Именно здесь следует ввести полезную функцию под названием "instanceof", который проверяет, является ли объект экземпляр какого-то класса.

 Cat c1 = new Cat();         
    Animal a = c1;       //upcasting to Animal
    if(a instanceof Cat){ // testing if the Animal is a Cat
        System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

для получения дополнительной информации, пожалуйста, прочитайте в этой статье

лучше попробовать этот метод для upcasting, это легко понять:

/* upcasting problem */
class Animal
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}

class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class Useanimlas 
{
    public static void main (String [] args) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}

может быть, эта таблица помогает. Вызываю callme() метод класса Parent или класс Child. В принципе:

UPCASTING -- > Hiding

DOWNCASTING -- > Revealing

enter image description here

enter image description here

enter image description here

Родитель: Автомобиль
Ребенок: Фигу
Автомобиль c1 = новый Figo ();

=====
Upcasting:-
Метод: объект c1 будет ссылаться на методы класса (Figo-метод должен быть переопределен), поскольку класс "Figo" указан с помощью "new".
Переменная экземпляра: объект c1 будет ссылаться на переменную экземпляра класса объявления ("Car").

когда класс объявления является родительским, а объект создается из дочернего, тогда происходит неявное приведение, которое является "Upcasting".

======
Приведения типов:-
Figo f1 = (Figo) c1; //
Метод: объект f1 будет ссылаться на метод класса (figo), поскольку исходный объект c1 создается с классом "Figo". но как только выполняется приведение вниз, методы, которые присутствуют только в классе "Figo", также могут быть отнесены к переменной f1.
Переменная экземпляра: объект f1 не будет ссылаться на переменную экземпляра класса объявления объекта c1 (класс объявления для c1-CAR), но с приведением вниз он будет ссылаться на экземпляр переменные класса Figo.

======
Использование: для объекта дочернего класса и класса-родитель и дочерний класс хочет получить доступ к переменной экземпляра собственного класса, а не родительского класса, тогда это можно сделать с помощью "приведения типов".

upcasting означает приведение объекта к супертипу, в то время как downcasting означает приведение к подтипу.

в java, upcasting не требуется, как это делается автоматически. И это обычно называют неявным кастингом. Вы можете указать его, чтобы сделать его понятным для других.

таким образом, пишет

Animal a = (Animal)d;

или

Animal a = d;

приводит к точно такой же точке и в обоих случаях будет выполнено callme() от Dog.

вместо этого необходимо понижение, потому что вы определили a как объект животного. В настоящее время вы знаете, что это Dog, но Java не имеет никаких гарантий это. На самом деле во время выполнения он может быть разным и Java бросит ClassCastException, это произошло. Конечно, это не очень пример. Если бы вы не бросили a до Animal, java даже не смог скомпилировать приложение, потому что Animal не имеет метода callme2().

в вашей например, вы не можете добраться до кода callme() на Animal С UseAnimlas (поскольку Dog перезаписать его), если метод не будет следующим:

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 

мы можем создать объект для понижения. В этом типе тоже. вызов методов базового класса

Animal a=new Dog();
a.callme();
((Dog)a).callme2();