문제

hullo 모두,

다음이 작동하지 않는 이유에 대해 저를 단서로 할 수있는 Java 해커가 있는지 궁금합니다.

public class Parent {
    public Parent copy() {
       Parent aCopy = new Parent();
       ...
       return aCopy;
    }
}

public class ChildN extends Parent {
    ...
}

public class Driver {
     public static void main(String[] args) {
         ChildN orig = new ChildN();
         ...
         ChildN copy = orig.getClass().cast(orig.copy());
     }
}

코드는 컴파일하는 것이 매우 행복하지만 런타임에서 클래스 캐스트 렉스크를 던지기로 결정합니다. d =

편집하다: 우와, 정말 빠른 대답. 감사합니다! 그래서이 방법을 사용하여 다운 캐스트 할 수없는 것 같습니다 ... Java에서 다운 캐스팅을 수행하는 다른 방법이 있습니까? 나는 각각에 대해 생각했다 ChildN 클래스 덮어 쓰기 copy(), 추가 보일러 플레이트 코드를 추가하는 것에 대해 열정적이지 않았습니다.

도움이 되었습니까?

해결책

(주석에 코드를 추가 할 수 없으므로 여기에 추가하겠습니다)

복제 가능에 대해 : 복제 가능성을 구현하는 경우 다음과 같이 구현하십시오. 전화하기가 훨씬 더 깨끗합니다 ...

public class Foo implements Cloneable {
    public Foo clone() {
        try {
            return (Foo) super.clone();
        } catch (CloneNotSupportedException e) {
            return null; // can never happen!
    }
}

편집 : 나는 또한 다른 사람들이 사용하는 것을 보았습니다

throw new AssertionError("This should never happen! I'm Cloneable!");

캐치 블록에서.

다른 팁

이것을 시도하는 것과 같습니다.

  public Object copy(){
       return new Object();
  }

그런 다음 시도합니다.

  String s = ( String ) copy();

당신의 부모의 수업 및 어린이 클래스는 같은 관계를 가지고 있습니다 물체 그리고

작동하려면 다음을 수행해야합니다.

public class ChildN extends Parent {
    public Parent copy() {
        return new ChildN();
    }
}

즉, "복사"메소드를 무시하고 올바른 인스턴스를 반환합니다.


편집하다

편집에 따라. 그것은 실제로 가능합니다. 이것은 가능한 한 가지 방법 일 수 있습니다.

public class Parent {
    public Parent copy() {
        Parent copy = this.getClass().newInstance();
        //...
        return copy;
    }
}

이렇게하면 각 서브 클래스에서 "복사"메소드를 무시할 필요가 없습니다. 이것이 프로토 타입 설계 패턴입니다.

그러나이 구현을 사용하면 두 가지 확인 된 예외를 알고 있어야합니다. 다음은 문제없이 컴파일하고 실행하는 완전한 프로그램입니다.

public class Parent {
    public Parent copy()  throws InstantiationException, IllegalAccessException  {
       Parent copy = this.getClass().newInstance();
       //...
       return copy;
    }
}
class ChildN  extends Parent {}

class Driver {
     public static void main(String[] args) throws  InstantiationException ,  IllegalAccessException  {
         ChildN orig = new ChildN();
         ChildN copy = orig.getClass().cast(orig.copy());
         System.out.println( "Greetings from : " + copy );
    }
}

캐스트는 효과적으로이 작업을 수행하려고합니다.

ChildN copy = (ChildN) orig.copy();

(실행 시간에 공연하기 위해 출연진을 사용하고 있지만 그게 바로 그럴 것입니다. orig.getClass() 될거야 ChildN.class) 하지만, orig.copy() Childn의 인스턴스를 반환하지 않으면 단지 인스턴스를 반환합니다. Parent, 따라서 캐스트 할 수 없습니다 ChildN.

If ChildN does not override copy() to return an instance of ChildN, then you are trying to downcast an object of type parent to type ChildN

java.lang.Class#cast(Object) throws a ClassCastException if Class#isInstance() returns false. From the javadoc for that method:

Determines if the specified Object is assignment-compatible with the object represented by this Class. This method is the dynamic equivalent of the Java language instanceof operator... Specifically, if this Class object represents a declared class, this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); it returns false otherwise.

Since Parent is not a subclass of child, isInstance() returns false so cast() throws the exception. This may violate the principle of least astonishment but it's working the way it's documented - cast() can only upcast, not downcast.

Could it be that you simply want a copy/clone of your object.

In that case, implement the Cloneable interface and override clone() as necessary.

public class Parent implement Cloneable {
   public Object clone() throws CloneNotSupportedException {
     Parent aCopy = (Parent) super.clone();
   ...
   return aCopy;
   }
}

public class ChildN extends Parent {
    ...
}

public class Driver {
     public static void main(String[] args) {
         ChildN orig = new ChildN();
         ...
         ChildN copy = orig.getClass().cast(orig.clone());
     }
}

This does exactly what your "copy()" method tried to do in the Java way.

(Yes, you could do fancy introspection games too, but those methods fail or become ugly as soon as you do not have a public default-constructor. Clone works in any case no matter what constructors you have.)

The reason downcasting doesnt work is because, when you cast a parent object to a child type, theres no way you can invoke child type's methods on the parent object. But it works the other way...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top