0

对不起标题...

我有一个像 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);

感谢您的任何回答,卡洛

4

5 回答 5

2

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

只是例子:

if(fd1 instanceOf Fd1Obj)
于 2013-06-18T10:49:00.287 回答
2

我想在编译时确定..

反射是关于运行时的。所以它对编译时间没有帮助。

于 2013-06-18T10:50:56.280 回答
0

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

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

这样你就可以确定类型检查是在编译时完成的。

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

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

看看这里:

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

并且没有反射对编译时检查没有那么大的帮助。

于 2013-06-18T11:53:12.187 回答
0

这在 Java 中是冗长的,但 Java8 的 lambdas 应该让它不那么冗长。您需要的是一种从 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 的 lambdas 将大大提高可读性:

foo(a1, a2, a -> a.fieldName);
于 2013-06-18T13:02:54.367 回答
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);
于 2013-06-18T10:51:55.877 回答