Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在没有公共接口的情况下调用公共方法_Java_Reflection - Fatal编程技术网

Java 在没有公共接口的情况下调用公共方法

Java 在没有公共接口的情况下调用公共方法,java,reflection,Java,Reflection,我有一些生成的代码(也就是说,它不能被更改),看起来像这样 class Generated1 { public String getA() { return "1"; } public void setB(String b) { } public void setC(String c) { } public void setD(String d) { } } class Generated2 { pu

我有一些生成的代码(也就是说,它不能被更改),看起来像这样

class Generated1 {
    public String getA() {
        return "1";
    }

    public void setB(String b) {
    }

    public void setC(String c) {
    }

    public void setD(String d) {
    }
}

class Generated2 {
    public String getA() {
        return "2";
    }

    public void setB(String b) {
    }

    public void setC(String c) {
    }

    public void setD(String d) {
    }
}
我正在通过反射探索这些物体。它们都没有实现任何公共接口,但有很多,我想将它们视为实现:

interface CommonInterface {
    String getA();

    void setB(String b);

    void setC(String c);

    void setD(String d);
}
这当然应该是可能的。这被认为是非常好的代码

class CommonInterface1 extends Generated1 implements CommonInterface {
    // These are perfectly good classes.
}

class CommonInterface2 extends Generated2 implements CommonInterface {
    // These are perfectly good classes.
}
我想我要找的是:

private void doCommon(CommonInterface c) {
    String a = c.getA();
    c.setB(a);
    c.setC(a);
    c.setD(a);
}

private void test() {
    // Simulate getting by reflection.
    List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
    for (Object object : objects) {
        // What is the simplest way to call `doCommon` with object here?
        doCommon(object);
    }
}

我知道我可以像这样使用
代理
,但我更喜欢使用更好的代理

private void test() {
    // Simulate getting by reflection.
    List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
    for (Object object : objects) {
        // What is the simplest way to call `doCommon` with object here?
        doCommon(adapt(object));
    }
}

private CommonInterface adapt(Object o) {
    return adapt(o, CommonInterface.class);
}

public static <T> T adapt(final Object adaptee,
                          final Class<T>... interfaceToImplement) {
    return (T) Proxy.newProxyInstance(
        adaptee.getClass().getClassLoader(),
        interfaceToImplement,
        // Call the equivalent method from the adaptee.
        (proxy, method, args) -> adaptee.getClass()
            .getMethod(method.getName(), method.getParameterTypes())
            .invoke(adaptee, args));
}
private void test(){
//模拟通过反射获取。
List objects=Arrays.asList(new-Generated1(),new-Generated2());
用于(对象:对象){
//在这里用object调用'docomon'最简单的方法是什么?
doCommon(适应(对象));
}
}
专用公共接口适配(对象o){
返回adapt(o,CommonInterface.class);
}
公共静态T适配(最终对象适配对象,
最终类…接口(实现){
return(T)Proxy.newProxyInstance(
adaptee.getClass().getClassLoader(),
接口执行,
//从适配器调用等效的方法。
(代理、方法、参数)->adaptee.getClass()
.getMethod(方法.getName(),方法.getParameterTypes())
.invoke(adaptee,args));
}

如果使用反射,则不需要两个
CommonInterfaceX
类,可以使用代理实现
CommonInterface

public class Wrapper implements InvocationHandler {
    private final Object delegate;

    public static <T> T wrap(Object obj, Class<T> intf) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Object proxy = Proxy.newProxyInstance(cl, new Class<?>[] {intf},
                        new Wrapper(obj));
        return intf.cast(proxy);
    }

    private Wrapper(Object delegate) {
        this.delegate = delegate;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Method dmethod = delegate.getClass().getMethod(
                method.getName(), method.getParameterTypes());
        return dmethod.invoke(delegate, args);
    }
}
公共类包装器实现调用处理程序{
私有最终对象委托;
公共静态T换行(对象对象对象,类intf){
ClassLoader cl=Thread.currentThread().getContextClassLoader();
objectproxy=proxy.newProxyInstance(cl,新类[]{intf},
新包装(obj));
返回intf.cast(代理);
}
专用包装器(对象委托){
this.delegate=委托;
}
@凌驾
公共对象调用(对象代理、方法、对象[]参数)
扔掉的{
方法dmethod=delegate.getClass().getMethod(
方法.getName(),方法.getParameterTypes());
返回dmethod.invoke(委托,参数);
}
}
您可以按如下方式使用此类:

List<Object> objects = Arrays.asList(new Generated1(), new Generated2());
for (Object object : objects) {
    CommonInterface proxy = Wrapper.wrap(object, CommonInterface.class);
    doCommon(proxy);
}
List objects=Arrays.asList(new-Generated1(),new-Generated2());
用于(对象:对象){
CommonInterface proxy=Wrapper.wrap(对象,CommonInterface.class);
doCommon(代理);
}

更新:请注意,相同的
包装器
类可用于任何接口。

无法在
Generated1
Generated2
之间实现静态类型关系

即使您创建了
CommonInterface1
CommonInterface2
,您仍然不能静态地使用
Generated1
对象作为
CommonInterface1
,因为
newgenerated1()
不是
CommonInterface1
(并且永远不会成为一个)

到目前为止,最简单的解决方案是更改代码生成,将
CommonInterface
添加到
Generated1
Generated2


如果这是绝对不可能的,那么避免代码重复的唯一其他方法就是进行反射。

如果您想替换为注释。我认为你可以很容易地做到

public class Generated {
    public String getA() {
        return "A";
    }

    public String sayHello(String name) {
        return "hello " + name;
    }
}

public class Helper {
    private static final String METHOD_NAME = "getA";
    private static final String METHOD_WITH_PARAM_NAME = "sayHello";

    public static void main(String[] args) throws Exception {
        Generated generated = new Generated();

        accessMethod(generated);
        accessMethodWithParameter(generated);
    }

    private static void accessMethod(Generated g) throws Exception {
        Method[] methods = g.getClass().getDeclaredMethods();
        for(Method method : methods) {
            if(isCommonMethod(method)) {
                String result = (String) method.invoke(g);
                System.out.println(METHOD_NAME + "() = " + result);
            }
        }
    }

    private static boolean isCommonMethod(Method m) {
        return m.getName().equals(METHOD_NAME) && m.getReturnType().equals(String.class);
    }

    private static void accessMethodWithParameter(Generated g) throws Exception {
        Method[] methods = g.getClass().getDeclaredMethods();
        for(Method method : methods) {
            if(isCommonMethodWithParameter(method)) {
                String result = (String) method.invoke(g, "Max");
                System.out.println(METHOD_WITH_PARAM_NAME + "(\"Max\") = " + result);
            }
        }
    }

    private static boolean isCommonMethodWithParameter(Method m) {
        return m.getName().equals(METHOD_WITH_PARAM_NAME) &&
                m.getReturnType().equals(String.class) &&
                m.getParameterTypes().length == 1 &&
                m.getParameterTypes()[0].equals(String.class);
    }

}
首先,创建接口
CommonInterface

interface CommonInterface {
    String getA();

    void setB(String b);

    void setC(String c);

    void setD(String d);
}
class Generated1 implements CommonInterface {
    @overide
    public String getA() {
        return "1";
    }

    @overide
    public void setB(String b) {
    }

    @overide
    public void setC(String c) {
    }

    @overide
    public void setD(String d) {
    }
}

class Generated2 implements CommonInterface {

    @overide
    public String getA() {
        return "2";
    }

    @overide
    public void setB(String b) {
    }

    @overide
    public void setC(String c) {
    }

    @overide
    public void setD(String d) {
    }
}
然后,创建2个类
Generated1
Generated2
继承的
CommonInterface

interface CommonInterface {
    String getA();

    void setB(String b);

    void setC(String c);

    void setD(String d);
}
class Generated1 implements CommonInterface {
    @overide
    public String getA() {
        return "1";
    }

    @overide
    public void setB(String b) {
    }

    @overide
    public void setC(String c) {
    }

    @overide
    public void setD(String d) {
    }
}

class Generated2 implements CommonInterface {

    @overide
    public String getA() {
        return "2";
    }

    @overide
    public void setB(String b) {
    }

    @overide
    public void setC(String c) {
    }

    @overide
    public void setD(String d) {
    }
}

你可以通过思考手动完成

public class Generated {
    public String getA() {
        return "A";
    }

    public String sayHello(String name) {
        return "hello " + name;
    }
}

public class Helper {
    private static final String METHOD_NAME = "getA";
    private static final String METHOD_WITH_PARAM_NAME = "sayHello";

    public static void main(String[] args) throws Exception {
        Generated generated = new Generated();

        accessMethod(generated);
        accessMethodWithParameter(generated);
    }

    private static void accessMethod(Generated g) throws Exception {
        Method[] methods = g.getClass().getDeclaredMethods();
        for(Method method : methods) {
            if(isCommonMethod(method)) {
                String result = (String) method.invoke(g);
                System.out.println(METHOD_NAME + "() = " + result);
            }
        }
    }

    private static boolean isCommonMethod(Method m) {
        return m.getName().equals(METHOD_NAME) && m.getReturnType().equals(String.class);
    }

    private static void accessMethodWithParameter(Generated g) throws Exception {
        Method[] methods = g.getClass().getDeclaredMethods();
        for(Method method : methods) {
            if(isCommonMethodWithParameter(method)) {
                String result = (String) method.invoke(g, "Max");
                System.out.println(METHOD_WITH_PARAM_NAME + "(\"Max\") = " + result);
            }
        }
    }

    private static boolean isCommonMethodWithParameter(Method m) {
        return m.getName().equals(METHOD_WITH_PARAM_NAME) &&
                m.getReturnType().equals(String.class) &&
                m.getParameterTypes().length == 1 &&
                m.getParameterTypes()[0].equals(String.class);
    }

}
输出为

getA() = A
sayHello("Max") = hello Max

实例化接口的实现。使用列表而不是列表
类CommonInterface1 extends Generated1实现CommonInterface
意味着所有
CommonInterface1
对象也都是
Generated1
对象,但反过来则不成立。如果您
new
Generated1
对象,则它不是
CommonInterface1
对象。如果您通过反射来探索它们,则不需要接口。只需通过反射查找特定的命名方法。如果有,就叫它。@ScaryWombat-添加了一个简单的问题。你有多少生成的X类?因为如果只有几个适配器类,那么只需编写几个适配器类即可实现公共接口并委托给adaptee对象。并使用instanceof了解要创建的适配器。即使你有很多,因为你正在使用代码生成,你也可以生成适配器类遗憾的是,
生成的…
类无法更改。使用
代理当然是一种选择,但如果可能的话,我想避免它。另请参见我的问题的结尾(在您发布此答案后添加),这是一种更简单的创建代理的机制。它们非常强大,但如果有其他选择,它们仍然值得避免。因为这只是更多的反射,不应该被需要。看看我的
//这些都是非常好的类。