反思有用吗?

时间:2013-06-18 10:46:07

标签: java reflection

对不起标题......

我有一个像foo()这样的方法,如下所示

public static <T> void foo(T fld1, T fld2) {
    // here i use some info from fld1 and some from fld2 in order
    // to do something
}
foo(a1.myField, a2.myField)
  • 我想在编译时确保myField实际上是一个对象的字段
  • 我想避免重复.myField两次
  • 我希望无法将该方法称为foo(a1.myField, a2.anotherField);

我不知道反思是否是我问题的答案。

我可以这样写:

static <C> void foo(C o1, C o2, String fieldName) {
    try {
        Object fld1 = o1.getClass().getField(fieldName).get(o1);
        Object fld2 = o2.getClass().getField(fieldName).get(o2);
        // here i use some info from fld1 and some from fld2 in order
        // to do something
    } catch (Exception e) {
    }
}

但是如果fieldName是C类的有效字段名

,我无法在编译时检查

有一个方法

会很有帮助
Field getField(Object field)

这样

getField(a1.myField)

等于

a1.getClass().getField("myField")

现在我写这个方法:

public static <T> Field getField(T o, Object fld) {
    Field rv = null;
    try {
        Field[] fields = o.getClass().getFields();
        for (Field field : fields) {
            Object f = field.get(o);
            if (f==fld) {
                rv = field;
                break;
            }
        }
    } catch (Exception e) {
    }
    return rv;
}

并以这种方式使用

getField(a1, a1.myField);

感谢任何回答,Carlo

5 个答案:

答案 0 :(得分:2)

您可以在运行时使用方法instanceOf进行检查。

只是示例:

if(fd1 instanceOf Fd1Obj)

答案 1 :(得分:2)

  

我想在编译时确定..

反思完全是关于运行时。 所以对编译时间没有帮助。

答案 2 :(得分:0)

静态通用如何确保它是一个对象:

static <T extends Object> void foo(T fld1, T fld2) {
   // ...
}

您可以使用反射从对象中获取命名字段:

AType myField1 = (AType)fld1.getClass().getField("myField").get(fld1);
AType myField2 = (AType)fld2.getClass().getField("myField").get(fld2);

答案 3 :(得分:0)

您可以在调用foo(..)时指定类型,如:

  

yourClass.foo(a1.myField,a2.myField)。

通过这种方式,您可以确保在编译时完成类型检查。

但是,这不是强制性的,如果你不提供类型参数,即在这种情况下,java文档说:

  

推理算法试图找到最具体的类型   适用于所有论点。

看看这里:

  

http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

没有反映对编译时间检查没有帮助。

答案 4 :(得分:0)

这在Java中很冗长,但Java8的lambda应该不那么简单。你需要的是一种编译时检查的从类型C的对象到类型T的值的方法。在Java中指定它的方式是一个接口:

public interface Getter<C, T> {
  T get(C c);
}

然后将您的功能指定为

static <C, T> void foo(C c1, C c2, Getter<C, T> getter) {
  T fld1 = getter.get(c1);
  T fld2 = getter.get(c2);
  // ...
}

你这样称呼它 - 这是令人烦恼的部分:

foo(a1, a2, new Getter<A, Integer>() {
    public Integer get(A a) { return a.fieldName; }
});

Java8的lambda将使这个更具可读性:

foo(a1, a2, a -> a.fieldName);