Java:使用相同的代码和两个不同版本的依赖类

时间:2014-03-23 09:07:30

标签: java

考虑使用库 Bar 的Java类 Foo Foo 应作为二进制.class文件分发,并使用已存在于客户端类路径中的 Bar 版本。

有两种不同版本的 Bar 只在方法签名上有所不同。 Foo 应与这两者兼容。

示例代码:

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);
    }
}

如果可能,我想避免反思。您如何建议创建一个与 Bar 的两个版本兼容的类 Foo

[编辑]

这个问题起源于我正在研究的项目。 Bar 对应我正在使用的外部库但无法修改代码才能工作(我没有源代码,许可证也不允许修改)。

4 个答案:

答案 0 :(得分:1)

反射似乎是最简单的方法。另一种方法是尝试调用第二个版本并捕获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");
        }
}

这很难看,而且速度较慢,请使用Reflection来实现其目的。

答案 1 :(得分:1)

听起来这是由strategy pattern处理的一项任务。

答案 2 :(得分:1)

反思性解决方案。

    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);
    }

您可以使用c = Bar.class;或者您已经拥有Bar c = bar.getClass()的实例栏。如果非静态方法需要v1method.invoke(bar,"V1");

,则调用语法适用于静态方法

答案 3 :(得分:0)

我假设:

  1. 您无法更改任何版本的Bar类文件
  2. 您可以编写新的Foo文件
  3. 出于某种原因,您确实希望避免使用Reflection
  4. 两个Bar文件具有相同的包名称
  5. 您可能需要分发两个版本的Foo类,如JB Nizet在您的问题评论中所述。