2013-08-07 1 views
3

라이브러리에 대해 프로그래밍하고 있습니다.NoSuchMethodError를 피하려면 반사가 필요합니까?

버전 1에서 해당 라이브러리 버전 2에서지도

을 반환하는 방법 getFoo()를 가지고, 그 방법 getFoo()가 현재 설정

내가 생각 반환 내 코드 행복하게 수 :

Object foo = library.getFoo(); 

라이브러리가지도 또는 세트를 반환하는지 여부에 관계없이 작동합니다.

그러나 라이브러리의 버전 1에 대해 코드를 컴파일하지만 버전 2에 대해 실행하면 java.lang.NoSuchMethodError가 발생합니다. getFoo() Ljava/util/Map;

는 적어도 그게 내가 지금 반사를 사용하여이 문제를 해결했습니다

java version "1.7.0_21" 
OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.04.1) 
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode) 

에 무슨 일이지만, 내가해야 할 것이라고 생각하지 않았다.

내 질문은 Object foo = library.getFoo()를 실행하는 것이 안전한지, 그 대답이 "때때로"또는 "의존"인 경우 왜이 경우에는 좋지 않은지입니다. ?

+4

다른 라이브러리가있는 코드를 작성하고 다른 라이브러리와 동일한 코드를 실행하는 것은 그 자체로 문제가 있습니다. 나는 당신이 코드에서 그것을 다루는 대신에 lib 불일치를 바로 잡아야한다고 믿는다. –

+0

그것은 매우 힘든 질문입니다 ... 당신은 그것이 완벽하게 괜찮을 것이라고 생각할 것입니다. 이제는 Map과 Set이 모두 인터페이스라는 것을 알고 있습니다. [Map] (http://docs.oracle.com/javase/6/docs/api/java/util/Map.html) 및 [Set] (http://docs.oracle.com/javase)에 대한 javadocs 확인 /6/docs/api/java/util/Set.html)'Set'은'Collection'을 확장하고 Map은 아무 것도 확장하지 않는다는 것을 보여줍니다. 이것과 관련이 있습니까? 'Map'은 수식어가''이고'Set'는'' 만 가질 수 있습니다. – snickers10m

+0

사실, 제가 생각하기에 두 번째 생각은 그곳의 문제입니다.''의'Set'을 반환하기 때문에지도는''두 개를 제공하지만 호환되지 않습니다. 어쩌면 그들은 단지이 경우를 위해 새로운 것을 만드는 대신에 그 기본 오류 메시지를 주었을 것입니다. – snickers10m

답변

1

버전 1을 사용하여 코드를 컴파일하면 클래스 바이트 코드에이 메소드에 대한 항목이 반환 유형이 Map으로 있습니다. 런타임에 클래스가로드되고 클래스 정의에는 Map과 같은 반환 유형이있는 getFoo()가 있으므로 JVM에서는 다른 반환 유형의 메소드가있는 다른 버전의 클래스에 대해이를 실행하므로 메소드를 찾을 수 없습니다. 귀하의 경우).

0

오류는 완벽하게 유효합니다.

옵션 1 : 코드에서 리플렉션을 사용하면 런타임에 발견 한 라이브러리의 버전에 관계없이 동적으로 올바른 작업을 수행 할 수 있습니다.

옵션 2 : 두 버전의 라이브러리에서 코드를 실행하려면 컴파일시 두 버전을 모두 사용할 수 있어야합니다. 런타임에 사용되는 버전을 결정하고 적절한 버전의 라이브러리를 호출하도록 컴파일 된 코드를 조건부로 실행하려면 일부 코드가 필요합니다. 라이브러리 작성자가 불친절했다면 클래스 이름 충돌을 피할 필요가 있습니다.

반사 (옵션 1)는 가장 쉽고 유연한 접근 방법입니다.

라이브러리의 두 버전 간 차이점을 추상화하는 래퍼 API를 만들어이 응용 프로그램의 나머지 부분으로 누출되지 않도록 할 수 있습니다.

관련 문제