是否有可能通过反射获得一个字段而不抛出异常(如果它不存在)

时间:2016-03-15 23:14:03

标签: java reflection

如果下面的语句被调用数千次,那么如果有许多类没有名为' id'的字段,那么它将非常慢。有没有办法通过使用java中的反射获取字段,如果字段不存在则不会抛出异常?

Field f2 = null;
try{
    f2 = classThatMightNotHaveFieldId.getClass().getDeclaredField("id"); 
    f2.setAccessible(true);
}catch(Exception e){
    System.out.println(f1.get(classThatMightNotHaveFieldId));           
}

2 个答案:

答案 0 :(得分:1)

查看以下类getDeclaredField()方法的定义:

public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException {

据此,它可以抛出以上两个例外。现在,看一下实现:

if (field == null) {
    throw new NoSuchFieldException(name);
}

所以,它会抛出一个异常的字段未找到。如果我们想要压缩它,我们将不得不使用FieldUtils类的Apache commons库,如果找不到字段则返回null,例如:

class Test3{        
    private int field1;
}

public class Test {
    public static void main(String[] args) throws Exception {
        Test3 test3 = new Test3();
        Field declaredField = FieldUtils.getDeclaredField(Test3.class, "field1", true);
        Field declaredField2 = FieldUtils.getDeclaredField(Test3.class, "field2", true);
        System.out.println(declaredField);
        System.out.println(declaredField2);
    }
}

此示例为第一个字段打印hashCode,为第二个字段打印null。

答案 1 :(得分:1)

回答您是否有可能找到没有抛出异常的字段的具体问题:是的,您可以调用Class.getDeclaredFields()来获取该类的所有字段,然后遍历它们以找到一个适当的名称:

for (Field field : clazz.getDeclaredFields()) {
  if (field.getName().equals("id")) {
    // Do whatever.
    break;
  }
}

应该注意的是,虽然这不会引发异常,但它并不比仅仅调用class.getDeclaredField("id")并吞噬异常更快(并且通常更慢)(通过非常粗略的微基准测试)。 clazz.getDeclaredFields()在返回之前制作防御的字段副本,因此在调用此方法时还有很多额外的工作要做。

您未在问题中提供实际使用模式的详细信息;您应该进行一些实验,看看是否可以通过现有实现的替代方法实现加速(如某种缓存)。