В чем разница между перебрасыванием и понижающим литьем по отношению к переменной класса

В чем разница между перебросом и понижающим литьем по переменной класса?

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

Если выполняется кастинг, то как мы можем вызвать метод 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();
    }
}

Ответ 1

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

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

Даункинг будет примерно таким:

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 и выдает ClassCastException.

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

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

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

Ответ 2

Преобразование и преобразование было следующим:
enter image description here

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

Даункастинг: когда мы хотим преобразовать суперкласс в субкласс, мы используем даункастинг (или сужение), и даункастинг напрямую не возможен в 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 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

Ответ 3

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

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

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

Ниже приведен пример, как getType(); работает в соответствии с типом объекта (Dog, Pet, Police Dog).

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

  • Собака - это суперкласс.
  • Pet Dog - Pet Dog расширяет Собака.
  • Полицейская собака - полицейская собака расширяет собаку.

    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

Даунсайдинг должен выполняться программистом вручную

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

  ( (PoliceDog)obj3).secretID();

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

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

  ( (PetDog)obj2).dogName();

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

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

Примечание. Здесь, ссылаясь на то, что вы не меняете адрес памяти ваших проектов, когда вы опускаете его, он по-прежнему остается таким же, вы просто группируете их по определенному типу в этом случае Dog

Ответ 4

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

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

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

  • Но downcasting всегда нужно делать вручную:

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

Почему это так, что восходящий поток является автоматическим, но downcasting должен быть ручным? Ну, вы видите, повышение может никогда не потерпеть неудачу. Но если у вас есть группа разных животных и вы хотите превзойти их всех в Cat, то есть шанс, что некоторые из этих животных на самом деле являются Собаками, а процесс терпит неудачу, бросая 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 a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

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

Ответ 5

Лучше попробуйте этот метод для повышения, это легко понять:

/* 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();
    }
}

Ответ 6

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

ОБНОВЛЕНИЕ → Скрытие

DOWNCASTING → Выявление

enter image description here

enter image description here

enter image description here

Ответ 7

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

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

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

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

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

Ответ 8

1.- Обновление.

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

Animal animalCat = new Cat();

Что означает, что такой тег animalCat будет иметь функциональность (методы) только типа Animal, потому что мы объявили его как тип Animal, а не как тип Cat.

Нам разрешено делать это "естественным/неявным/автоматическим" способом, во время компиляции или во время выполнения, главным образом потому, что Cat наследует некоторые из своих функций от Animal; например, move(). (По крайней мере, кот это животное, не так ли?)

2.- Даункинг.

Но что произойдет, если нам потребуется получить функциональность Cat из нашего тега Animal типа?.

Поскольку мы создали тег animalCat, указывающий на объект Cat, нам нужен способ вызывать методы объекта Cat из нашего тега animalCat довольно умным способом.

Такую процедуру мы называем Downcasting, и мы можем сделать это только во время выполнения.

Время для некоторого кода:

public class Animal {
    public String move() {
        return "Going to somewhere";
    }
}

public class Cat extends Animal{
    public String makeNoise() {
        return "Meow!";
    }   
}

public class Test {

    public static void main(String[] args) {

    //1.- Upcasting 
    //  __Type_____tag________object
        Animal animalCat = new Cat();
    //Some animal movement
        System.out.println(animalCat.move());
        //prints "Going to somewhere"

    //2.- Downcasting   
    //Now you wanna make some Animal noise.
        //First of all: type Animal hasn't any makeNoise() functionality.
        //But Cat can do it!. I wanna be an Animal Cat now!!

        //___________________Downcast__tag_____ Cat method
        String animalNoise = ( (Cat) animalCat ).makeNoise();

        System.out.println(animalNoise);
        //Prints "Meow!", as cats usually done.

    //3.- An Animal may be a Cat, but a Dog or a Rhinoceros too.
        //All of them have their own noises and own functionalities.
        //Uncomment below and read the error in the console:

    //  __Type_____tag________object
        //Cat catAnimal = new Animal();

    }

}

Ответ 9

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

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

Таким образом, запись

Animal a = (Animal)d;

или

Animal a = d;

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

Вместо этого требуется downcasting, потому что вы определили a как объект Animal. В настоящее время вы знаете это 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");
    }
    ... 
} 

Ответ 10

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

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