简体   繁体   中英

Reflection necessary to avoid NoSuchMethodError?

I'm programming against a library.

In version 1, that library had a method getFoo() which returned a Map

In version 2, that method getFoo() now returns a Set

I thought that my code could happily:

  Object foo = library.getFoo();

and work whether the library returns a Map or a Set.

However, when I compile my code against version 1 of the library, but run it against version 2, I get java.lang.NoSuchMethodError: getFoo()Ljava/util/Map;

At least that is what happens with

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)

I've now addressed this by using reflection, but I hadn't thought that would be necessary.

So my question is, is it ever safe to do Object foo = library.getFoo(), and if the answer to that is "sometimes" or "it depends", then why wasn't it ok in this case?

When you compiled the code using version 1, your the class byte code has entry for this method with return type as Map. At runtime the class is loaded, class definition has getFoo() with return type as Map, and hence JVM is not able to locate the method since you are running it against a different version of the class which has method with different return type(Set in your case).

The error you are getting is perfectly valid.

Option 1: Use reflection in your code to dynamically do the right thing with whatever version of the library you find at runtime.

Option 2: If you want your code to run with either version of the library, you will need both versions available at compile time. You will need some code to decide which version is being used at runtime and conditionally execute your code that was compiled to call the proper version of the library. If the library author was unkind, you may end up having to work around class name conflicts.

Reflection (option 1) is likely to be the easiest and most flexible approach.

You probably want to create a wrapper API that abstracts the differences between the two versions of the library, so this ickiness doesn't leak into the rest of your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM