2012-05-13 4 views
1

내 작업 공간에 3 개의 프로젝트가 있습니다. A, B, C는 Android lib 프로젝트입니다.리플렉션을 통해 검색된 Class 객체를 인터페이스로 전송할 수 있습니까?

  1. 는 B가이 인터페이스를 구현 IBtest라는 클래스가 포함 Atest
  2. 라는 활동을 포함한다.
  3. C는 I 인터페이스를 포함합니다.

Android 기기에 A와 B가 모두 설치되어 있습니다. 이제 여기

Context otherContext = createPackageContext("com.package.b", 
       CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY); 
ClassLoader loader = otherContext.getClassLoader(); 
Class<?> btest = Class.forName("com.package.b.BTest", true, loader); 

내 질문은 - A 실행 컨텍스트 내에서 I에 btest 캐스팅 할 수있는 방법이있다 : Atest 런타임 동안 , 내가 다음 코드를 실행하는거야?

나는 많은 명백한 (그리고 그렇게 그리 명백한 몇 가지) 트릭을 시도했지만 아무런 성과가 없었다. 내가 할 수의 코스 등의 방법을 호출 btest의 방법과 인터페이스를 탐구 ..하지만 A와 B 모두

C.

lib 디렉토리 프로젝트에 동일한 I 인터페이스를 참조하지만 나는 단순히, I으로 캐스팅 할 수 없습니다 미리 감사드립니다!

P.

오브젝트에 들어 가지 않고 인터페이스에 캐스팅 했으므로이 경우에는 ClassLoader이 원인이 아닙니다.

답변

1

런타임에이 동적로드 작업을 모두 수행하기 때문에 가상 메소드 테이블 및 관련 vpointer가 생성되지 않습니다. 따라서 런타임에서 인터페이스 메소드에 대한 호출을 동적으로 적절히로드 된 구현으로 디스패치 할 수있는 방법이 없습니다. 리플렉션을 사용해야합니다.

+0

간단하고 명확합니다. "invoke"를 통해 객체 메쏘드에 접근하는 것을 피할 수 있습니까? 리플렉션을 통해 해당 개체에 액세스해야합니다 ... – avimak

0

인터페이스 I은 클래스 경로에 있어야하며 그렇지 않으면 런타임에서로드 할 수 있어야합니다. 그렇지 않으면 런타임 예외가 발생합니다. Reflection을 사용하면이 문제를 피할 수 없습니다.

+0

'A'는'C'에 연결되어 있으므로'I'가 classpath에 있습니다. – avimak

+0

예, 'C'가 사용 가능한 클래스이면 'I'를로드 할 수 있음을 의미합니다. 너 정확히 뭘 하려구? –

+0

나는'Btest'를'I'로 언급하고 싶습니다. 나는 할 수 없습니다. Object 또는 Class /Class 객체로만 참조 할 수 있습니다. 즉, 구현 된 인터페이스 메소드를 직접 호출 할 수는 없지만 "invoke"를 사용할 수는 있습니다. 지금은 더 명확한가요? – avimak

1

귀하의 질문에 몹시 불명확하므로 귀하의 뜻을 추측해야합니다.

먼저, 자바에는 Interface 클래스가 없다, 그래서 당신이 의미 할 수 없습니다 그래서

Interface<?> i = // some magic transformation of btest 

, 난 당신이 인터페이스에 com.package.b.BTest의 인스턴스를 캐스팅에 대해 얘기하는 가정 (의 그것을 호출 할 수 있습니다. ..) com.package.i.I. BtestI 모두 정적으로로드

  • 경우, (I) bTestInstance이 작업을 수행합니다.

  • Btest 동적으로로드 된 경우

    Btest 구현 I는 다음 작업을해야합니다 :

    Class<?> btestCls = Class.forName("com.package.b.BTest", true, loader); 
        // This will work, because I has to be on the classpath of 'loader' 
        // for the previous load to work ... 
        Class<?> iCls = Class.forName("com.package.i.I", true, loader); 
    
        Object btest = // create a BTest instance reflectively 
        Object i = iCls.cast(btest); 
    

    물론 문제는 코드가 동적으로 BTestI로드하기 때문에, 쓸 수있는 방법이 없다는 것입니다 정적 유형이 BTest 또는 I 인 변수 따라서 캐스트는 BTestI을 구현한다고 주장하는 것을 제외하고는 실제 목적으로 사용되지 않습니다.

다른 가능성은 클래스 객체를 형 변환하는 것입니다. 그러나 이것은 Class에 대한 유형 매개 변수로 와일드 카드를 사용해야한다는 점에서 어떤 의미가 없습니다. 정적 코드에 연결되지

Object btest = // create or retrieve the instance reflectively 
I i = (I) btest; 

I 경우 (명백하게) 당신이 I i를 선언 할 수 없습니다 : I 정적으로 당신이 할 수있는 코드에 연결되어있는 경우


그냥 반복합니다 위의, 그리고 btest 인스턴스에서 모든 조작에 대한 반사를 사용해야합니다. 정적 타이핑을 반사적으로 "할"수는 없습니다. 기간.

+0

왜 그렇게 명확하지 않습니까? 나는 리플렉션을 통해 객체를 가져오고 있습니다. 객체는'I' 인터페이스를 구현하고 있으며,'run' 컨텍스트에서'Class' 객체가 아닌'I'로 참조하고, 호출을 건너 뛰고 액세스합니다. 'A'와'B' 모두가 알고 있고 접근 할 수있는 인터페이스를 통한 데이터. 'B' 컨텍스트에서 실행되는 동안, 나는 물론'Btest'을'I'로 캐스팅 할 수 있습니다. 이것은 정확하게'A' 컨텍스트에서 실행되는 동안 달성하려는 것입니다. – avimak

+0

"클래스 객체가 아닌 내 실행 컨텍스트에서"이 것이 명확하지 않습니다. 'I'를 구현하는 클래스 객체와 객체는 완전히 다릅니다. –

+0

"I을 구현하는 클래스 개체와 개체는 완전히 다릅니다."; 당연하지. 내가 말한 것은 Object obj = btest.newInstance()를 호출하고 obj를'I'로 캐스팅하는 것입니다. 나는 왜 당신들에게 이상한 소리가 나는지 이해하지 못합니다. 검색된 객체에 액세스 할 수 없지만 리플렉션을 사용하기 때문에 obj를 알려진 인터페이스 인 I로 캐스팅하고 저장할 수 있을지도 모른다고 생각했습니다. 저들은 모두'나는'메소드를 호출하여 호출합니다. 지금은 더 명확한가요? – avimak

관련 문제