繁体   English   中英

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

[英]Java: Use the same code with two different versions of a dependent class

考虑使用库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对应于我正在使用的外部库,但无法对其进行修改以使代码正常工作(我没有源代码,并且许可证不允许进行修改)。

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

听起来这是一项由策略模式处理的任务。

一种折衷的解决方案。

    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");则调用语法适用于静态方法v1method.invoke(bar,"V1");

我假设:

  1. 您不能更改Bar类文件的任何版本
  2. 您可以编写新的Foo文件
  3. 由于某些原因,您确实要避免使用Reflection
  4. 两个Bar文件具有相同的包名称

您可能需要分发Foo类的两个版本,正如JB Nizet在对问题的评论中提到的那样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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