2012-04-06 2 views
7

나는 컴파일 타임에 클래스를 확장 할 수 있지만 이미 인스턴스화 된 수퍼 클래스의 인스턴스를 사용하여 런타임에이 서브 클래스의 인스턴스를 만들 수 있어야합니다.Java : 런타임시 클래스 확장

슈퍼 클래스 생성자는 이미 서브 클래스 생성자보다 먼저 호출되기 때문에 이론적으로 가능해야합니다.

인스턴스화를 내 서브 클래스로 변경하거나 원래의 인스턴스화를 방해하지 않을 정도로 프로그램에 대한 액세스 권한이 없습니다.

사용 사례 : X 클래스 인스턴스의 기존 배열이 있습니다. 내 코드가 나중에로드됩니다. 인스턴스 X 중 하나의 메서드 중 하나를 재정의해야합니다.로드 된 하위 클래스 Y는 X를 확장합니다. 부모 프로그램은 해당 배열을 통해서만 객체에 액세스하므로 배열 요소를 Y 인스턴스로 대체하려고합니다. 원래 그 배열에 인스턴스화 된 것처럼 작동합니다. 수퍼 클래스 인스턴스를 둘러싸고 호출을 전달할 수는 없으며 수퍼 클래스를 다시 인스턴스화하는 데 어려움이 있습니다.

나는 그것이 더 명확 할 것을 희망한다.

+3

질문을 수정하십시오. –

+1

실제로 달성하려는 것을 보여 줄 수 있습니까? 그렇게하는 대신 원하는,하지만 불가능한 방법 일뿐입니다. – millimoose

+0

기존 라인을 "public static Foo foo = new Foo();"라고 가정하십시오. 나는 바꿀 수 없다. 나는 "Public class Bar extends Foo"를 가지고 있고 첫 번째 라인이 "public static Foo foo = new Bar()"인 것처럼 "foo = new Bar (...)"를하고 싶습니다. – JAKJ

답변

5

당신이하려는 일을 반복하십시오 ..

JVM 내에서 ClassA의 인스턴스가 존재합니다. ClassA에서 파생되는 ClassB라는 새로운 클래스가 존재하도록 ClassA의 클래스 계층 구조를 동적으로 수정하려고합니다. 그런 다음 ClassB의 인스턴스를 인스턴스화하지만 하위 클래스 구현은 ClassA의 기존 인스턴스와 동일하게 구현해야합니다. 메모리 교체 같은 것.

http://www.jboss.org/javassist을 살펴볼 수 있습니다. 당신이해야 할 일은 ClassLoader를 대체 한 다음 ClassA가로드 될 때를 결정한 다음 인스턴스화하는 것입니다. 그런 다음 ClassB를 생성하여 대신 반환해야합니다.

업데이트

는 좀 더 연구하면 아직도 당신이 당신이 원하는 것을 할 수있는 가능성이 있습니다. Eclipse와 같은 IDE는 디버깅 중에 메소드 구현을 HotSwaping하는 것을 지원합니다. 그들은 Instrumentation API를 사용합니다.

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

당신은 방법 기관을 대체하지만 추가하거나 방법 자체를 제거 할 수 없습니다. 따라서 유형을 새 유형으로 변경할 수는 없지만 메소드 구현을 새 구현으로 완전히 바꿀 수 있습니다.

+0

나는 런타임시 상속을 변경하지 않고 수퍼 클래스가 이미 인스턴스화되었을 때 서브 클래스를 인스턴스화하기 만한다. – JAKJ

+0

@JAKJ 대답은 여전히 ​​동일합니다. 다른 유형의 객체에 적용 할 기존 객체가 있습니다. 이 새 객체의 초기 반환 지점을 제어 할 수 있으면 Adapted하고 원하는 인스턴스를 반환 할 수 있습니다. 솔루션으로 생각하는 것이 아니라 유스 케이스로 질문을 업데이트하는 것이 좋습니다. –

+0

슈퍼 클래스 다음에 클래스가로드되거나 제 3 자 런타임을 사용할 수 없으므로 클래스 로더를 바꿀 수있는 기능이 없습니다. 이것은 Java 내에 있어야합니다. – JAKJ

1

Java 프록시를 보았습니까?

"(이하 단지 프록시 클래스라고 함) 동적 프록시 클래스는 클래스가 생성 될 때 실행시 지정된 인터페이스의리스트를 구현하는 클래스 인"여기

는 자바 독에서 니펫
+0

프록시는 인터페이스가 아니라 클래스 인 것처럼 보입니다. – JAKJ

3

내가 cglib을 사용하는 것이 좋습니다 것입니다 :

CGLIB는 강력하고 높은 성능과 품질 코드 생성 도서관이다, 런타임에 인터페이스 을 자바 클래스를 확장하는 데 사용하고 구현한다

당신에게 여기에 몇 가지 예가 나와있을 수 있습니다.

2

나는 해결책이 될지 모르겠지만 갖고 있다면

public static Foo foo = new Foo(); 

는 당신은 푸 이 바 인스턴스에 foo는 점을 수 있도록 푸 사용 반사를 위해 바에게 래퍼을 확장 바로 교체합니다.

으로

public class Foo extends Bar { 
    private bar; 
    public Foo(Bar oldInstance) { 
    this.bar = oldInstance; 
    } 
} 

// exception handling ommitted 
public static void onStartup() { 
    Class fooRefClass = FooRef.class; 
    Field fooRef = fooRefClass.getDeclaredField("foo"); 

    Foo foo = (Foo)fooRef.get(null); 
    Bar bar = new Bar(foo); 
    fooRef.set(null, bar); 

은}이 귀하의 경우 가능하면 나도 몰라했다.

관련 문제