[java] 클래스 변수와 관련하여 업 캐스팅과 다운 캐스팅의 차이점은 무엇입니까?

클래스 변수와 관련하여 업 캐스팅과 다운 캐스팅의 차이점은 무엇입니까?

예를 들어 다음 프로그램 클래스 Animal에는 하나의 메서드 만 포함되어 있지만 Dog 클래스에는 두 가지 메서드가 포함되어 있습니다. 그러면 Dog 변수를 Animal 변수로 캐스팅하는 방법이 있습니다.

캐스팅이 완료되면 Animal 변수를 사용하여 Dog의 또 다른 메소드를 어떻게 호출 할 수 있습니까?

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



답변

업 캐스팅은 수퍼 타입으로 캐스트되고 다운 캐스팅은 서브 타입으로 캐스트됩니다. 업 캐스팅은 항상 허용되지만 다운 캐스팅에는 유형 검사가 필요하며를 던질 수 있습니다 ClassCastException.

귀하의 경우,에서 주조 Dog로는 AnimalA가 있기 때문에 업 캐스팅입니다 Dog입니다-A Animal. 일반적으로 두 클래스간에 관계가있을 때마다 상향 변환 할 수 있습니다.

다운 캐스팅은 다음과 같습니다.

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()업 캐스트를 수행하거나 수행하십시오.

서브 클래스의 메소드를 호출하려면 다운 캐스트를 수행해야합니다. 위에 표시된 것처럼 일반적 ClassCastException으로이 작업을 수행하면 위험 할 수 있습니다 . 그러나 instanceof캐스트를 수행하기 전에 연산자를 사용하여 객체의 런타임 유형을 확인할 수 있습니다 ClassCastException.

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


답변

다운 캐스팅 및 업 캐스팅은 다음과 같습니다.
여기에 이미지 설명을 입력하십시오

Upcasting : Sub 클래스를 Super 클래스로 캐스팅하려면 Upcasting (또는 widening)을 사용합니다. 명시 적으로 아무것도 할 필요가 없으며 자동으로 발생합니다.

다운 캐스팅 : Super 클래스를 Sub 클래스로 캐스팅하려면 다운 캐스팅 (또는 축소)을 사용하며 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


답변

업 캐스팅 및 다운 캐스팅은 Java의 중요한 부분으로, 간단한 구문을 사용하여 복잡한 프로그램을 작성할 수 있으며 다형성 또는 다른 객체 그룹화와 같은 큰 이점을 제공합니다. Java는 서브 클래스 유형의 오브젝트가 모든 수퍼 클래스 유형의 오브젝트로 처리되도록합니다. 이를 업 캐스팅이라고합니다. 업 캐스팅은 자동으로 수행되지만 다운 캐스팅은 프로그래머가 수동으로 수행해야하며 그 이유를 설명하기 위해 최선을 다할 것입니다.

업 캐스팅 및 다운 캐스팅은 프리미티브를 서로 캐스팅하는 것과 같지 않으며 프로그래머가 객체 캐스팅을 배우기 시작할 때 많은 혼란을 초래하는 것이라고 생각합니다.

다형성 : 자바의 모든 메소드는 기본적으로 가상입니다. 즉, 메소드가 final 또는 static으로 선언되지 않은 경우 상속에 사용될 때 모든 메소드를 대체 할 수 있습니다 .

아래 예제 getType();는 object (Dog, Pet, Police Dog) 유형에 따라 어떻게 작동 하는지 볼 수 있습니다 .

세 마리의 개가 있다고 가정

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

다형성 : 자바의 모든 메소드는 기본적으로 가상입니다. 즉, 메서드가 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()방법. 해당 메소드를 호출하려면 해당 obj3을 수동으로 다운 캐스트해야합니다. PoliceDog

  ( (PoliceDog)obj3).secretID();

인쇄 ID

인보 할 수있는 유사한 방법 dogName();으로 방법을 PetDog클래스는 다운 캐스트 필요 obj2PetDogobj2보다가 참조되기 때문에 Dog과에 액세스 할 수없는 dogName();방법을

  ( (PetDog)obj2).dogName();

왜 그렇게해서 업 캐스팅이 자동이지만 다운 캐스팅이 수동이어야합니까? 글쎄, 업 캐스팅은 결코 실패 할 수 없다. 당신이 다른 개 그룹이 자신의 유형에에 그들 모두를 다운 캐스트 싶은 경우, 다음 기회는 이러한 개 중 일부는 실제로 다른 유형의 수 있습니다 즉 것을, 거기 PetDog, PoliceDog및 프로세스가 던져 실패 ClassCastException.

객체를 수퍼 클래스 유형으로 참조한 경우 객체를 수동으로 다운 캐스트 해야하는 이유 입니다.

참고 : 여기에서 참조한다는 것은 다운 캐스트 할 때 객체의 메모리 주소를 변경하지 않고 여전히이 경우 특정 유형으로 그룹화하는 것과 동일하게 유지함을 의미합니다 Dog


답변

나는이 질문이 오래 전에 요청되었지만이 질문의 새로운 사용자를 위해 알고 있습니다. 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

왜 그렇게해서 업 캐스팅이 자동이지만 다운 캐스팅이 수동이어야합니까? 글쎄, 업 캐스팅은 결코 실패 할 수 없다. 그러나 다른 동물 그룹이 있고 모두 고양이로 다운 캐스트하려는 경우 이러한 동물 중 일부는 실제로 개이며 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 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()class Parent또는 class 의 메소드를 호출합니다 Child. 원칙적으로 :

UPCASTING-> 숨기기

DOWNCASTING-> 공개

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


답변

업 캐스팅.

업 캐스팅을 수행하면 하위 유형의 객체를 가리키는 일부 유형의 태그를 정의합니다 (더 편안하다고 느끼면 유형 및 하위 유형을 클래스 및 하위 클래스라고 할 수 있음).

Animal animalCat = new Cat();

이러한 태그 인 animalCat은 Cat 유형이 아닌 Animal 유형으로 선언 되었기 때문에 Animal 유형의 기능 (방법) 만 갖습니다.

우리는 “자연 / 암시 적 / 자동”방식으로 컴파일 타임이나 런타임에이를 수행 할 수 있습니다. 주로 Cat은 일부 기능을 Animal에서 상속하기 때문입니다. 예를 들어 move ()입니다. (적어도 고양이는 동물이 아닌가?)

다운 캐스팅.

그러나 Animal 태그 유형에서 Cat의 기능을 사용하려면 어떻게됩니까?

Cat 객체를 가리키는 animalCat 태그를 만들었으므로 animalCat 태그에서 Cat 객체 메서드를 스마트하게 호출하는 방법이 필요합니다.

이러한 절차는 다운 캐스팅이라고하며 런타임에만 수행 할 수 있습니다.

일부 코드 시간 :

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's 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();

    }

}