[英]Java: Use the same code with two different versions of a dependent class
Consider a Java class Foo that uses a library Bar . 考虑使用库Bar的Java类Foo 。 Foo should be distributed as a binary .class file and use the version of Bar that is already existing on a clients classpath.
Foo应该作为二进制.class文件分发,并使用客户端类路径上已经存在的Bar版本。
There are two different versions of Bar that only differ in its method signatures. Bar有两种不同的版本,只是其方法签名不同。 Foo should be compatible with both of them.
Foo应该与它们两者兼容。
Example code: 示例代码:
public class Foo {
public static void main(String[] args){
Bar.librarycall("hello from foo");
//or
Bar.librarycall("hello from foo",1);
}
}
//v1
public class Bar {
public static void librarycall(String argument){
System.out.println("Bar1: " + argument);
}
}
//v2
public class Bar {
public static void librarycall(String argument,int i){
for(int j = 0; j < i; j++)
System.out.println("Bar2: " + argument);
}
}
I want to avoid reflection if possible. 如果可能,我要避免反射。 How would you propose to create a class Foo that is compatible with both versions of Bar ?
您如何建议创建一个与Bar的两个版本都兼容的Foo类?
[Edit] [编辑]
This problem originates in a project I am working on. 此问题源于我正在从事的项目。 Bar corresponds to an external library I am using but cannot be modified for the code to work (I don't have the source code and the license doesn't allow modifications).
Bar对应于我正在使用的外部库,但无法对其进行修改以使代码正常工作(我没有源代码,并且许可证不允许进行修改)。
Reflection does seem like the simplest way. 反射似乎是最简单的方法。 The alternative would be to try calling the second version and catch a
NoSuchMethodException
. 另一种方法是尝试调用第二个版本并捕获
NoSuchMethodException
。
public class Foo {
public static void main(String[] args){
try {
Bar.librarycall("hello from foo",1);
catch(NoSuchMethodException e) {
Bar.librarycall("hello from foo");
}
}
This is ugly, and slower, use Reflection its what its there for. 这很丑陋,而且速度较慢,请使用Reflection及其功能。
听起来这是一项由策略模式处理的任务。
A refelective solution. 一种折衷的解决方案。
Class<?> c;
try {
c = Class.forName("Bar");
Method meths[] = c.getMethods();
Method v1method = null;
Method v2method = null;
for(Method m:meths) {
if(!m.getName().equals("librarycall")) continue;
if(!Modifier.isStatic(m.getModifiers())) {
System.out.println("Should be static");
continue;
}
Class<?> params[] = m.getParameterTypes();
if(params.length == 1 && params[0].equals(String.class) )
v1method = m;
if(params.length == 2 && params[0].equals(String.class) && params[1].equals(Integer.TYPE) )
v2method = m;
}
if(v2method!=null) {
v2method.invoke(null,"V2",5);
}
else if(v1method!=null) {
v1method.invoke(null,"V1");
}
else
System.out.println("No method found");
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
You could use c = Bar.class;
您可以使用
c = Bar.class;
or if you already have an instance bar of Bar c = bar.getClass()
. 或如果您已经具有Bar
c = bar.getClass()
的实例栏。 The invoke syntax is for static methods if its non static you need v1method.invoke(bar,"V1");
如果非静态方法需要
v1method.invoke(bar,"V1");
则调用语法适用于静态方法v1method.invoke(bar,"V1");
. 。
I'm assuming that: 我假设:
You may need to distribute two versions of the Foo class, as mentioned by JB Nizet in the comment to your question. 您可能需要分发Foo类的两个版本,正如JB Nizet在对问题的评论中提到的那样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.