如何在Java

时间:2015-05-29 17:50:58

标签: java generics methods

我在想,如果我有以下情况怎么办?

public class MyObject<T> {
   private T myTObject;

   public void setMyTObject(T m) { 
       myTObject = m;
   } 

   public T getMyTObject() { 
       return myTObject;
   }
}

现在我希望那个班级做出类似的反应:

MyObject<ObjectA> objA = new MyObject<ObjectA>();
ObjectA objAInstance = objA.getObjectA();

objA.setObjectA(otherObjectAInstance);

有没有办法根据T类名称动态创建方法? 或者我应该更好地将ObjectA扩展为MyObject并使用super.get / seMyObject()创建这些方法?

澄清:

我们的想法是动态生成getter和setter方法 所以,如果我创建一个实例:

MyObject<A> objA = new MyObject<A>();

我可以调用方法:

objA.getA();

getA()将在内部调用getMyTObject()或只返回myTObject

所以MyObject可能会根据T类做出反应并生成相应的方法。

我更新了成员属性以区别于MyObject类,这可能会导致混淆。还修复了方法返回和参数类型。

1 个答案:

答案 0 :(得分:0)

更新答案已完全更改。

听起来你想通过反思来使用某些东西。真正动态生成方法名称的问题在于,正如其他人所评论的那样,它必须在字节码中完成,这意味着尝试使用动态类的其他类没有Java代码可以引用。 可以完成,但这将是一团糟。

相反,这是使用泛型的可能解决方案。请注意,这是一个快速和肮脏的黑客;我留给你来改进它。您可以使用所需的getter和setter定义一个接口,无论您希望它们命名为什么:

package com.example.dcsohl;

public interface IntegerWrapper {

    public Integer getInteger();
    public void setInteger(Integer i);

}

然后,要使用它们,你可以使用这个类来完成繁重的工作。请注意,错误检查不是很好;例如,它没有检查&#34; getFoo&#34; at all对应于传入的类的名称;也没有证实&#34; foo&#34; in&#34; getFoo&#34;匹配&#34; setFoo&#34;方法。这是你可以改进的。

package com.example.dcsohl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyWrapper<T> implements InvocationHandler {

    Class<T> clazz = null;
    T myvalue = null;

    public static <W,T> W getInstance(Class<W> clazz, Class<T> clazz2) {
        ProxyWrapper<T> wrapper = new ProxyWrapper<T>();
        wrapper.setClass(clazz2);
        @SuppressWarnings("unchecked")
        W proxy = (W)Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] {clazz}, wrapper);
        return proxy;
    }

    private void setClass(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // getter has no arguments
        if (method.getName().startsWith("get") && (args == null || args.length == 0)) {
            return myvalue;
        } else if (method.getName().startsWith("set") && args.length == 1) {
            Object o = args[0];
            if (o.getClass().isAssignableFrom(clazz)) {
                @SuppressWarnings("unchecked")
                T val = (T)o;
                myvalue = val;
                return null;
            }
        } else {
            throw new Exception();
        }
        return null;
   }


}

最后,要使用它,这里有一个快速示例:

package com.example.dcsohl;

public class Main {

    public static void main(String[] args) {

        Integer foo = 5;

        IntegerWrapper wrapper = ProxyWrapper.getInstance(IntegerWrapper.class, Integer.class);
        wrapper.setInteger(foo);

        Integer bar = wrapper.getInteger();
        System.out.println(bar);
    }

}

似乎很多工作只是为了避免编写简单的包装类,而且你是对的,但反射有其用途,这是一个采样器。