【问题标题】:Is there a way to check if a field exists for a Generic class?有没有办法检查通用类的字段是否存在?
【发布时间】:2014-02-21 08:33:39
【问题描述】:

有没有办法检查通用类的字段是否存在?

public class Person {
    public String name;
    public String street;
    ...
}

public class Car {
    public String name;
    ...
}

public abstract class Base<E> {
    ...
    public void doSomething(E entity) {
        String street = "";
        //Check if the generic entity has a "street" or not.
        // If a Person arrives: then the real street should appear
        // If a Car arrives: then an empty string would be needed
        logger.trace("Entity name: {}", street);
    }

}

【问题讨论】:

  • 这可以通过反射来完成,但我真的认为你应该重新考虑你的设计。也许你可以基于接口做一些事情?

标签: java generics field


【解决方案1】:

我认为除了使用反射之外别无他法。应该是这样的(未测试):

try {
   Field field = entity.getClass().getField("street");
   if (field.getType().equals(String.class) {
      street = (String) field.get(entity);
   }
} catch (NoSuchFieldException ex) {
  /* ignore */
}

如果您可以控制类型层次结构,您可以使用getStreet() 方法创建一个类似HasStreet 的接口,并让您的带有街道的实体实现它。那会更简洁:只需检查该接口是否已实现,然后强制转换并调用该方法。

【讨论】:

    【解决方案2】:

    如果您可以减少 E 的不同选项,那么您可以使用instanceof 来检查类:

    public abstract class AbstractEntity {
        public string name;
    }
    
    public class Person extends AbstractEntity {
        public String street;
        ...
    }
    
    public class Car extends AbstractEntity {
    
        ...
    }
    
    public abstract class Base<E extends AbstractEntity> {
        ...
        public void doSomething(E entity) {
            String street = "";
            //Check if the generic entity has a "street" or not.
            // If a Person arrives: then the real street should appear
            // If a Car arrives: then an empty string would be needed
            if (entity instanceof Person) {
                Person p= (Person) entity;
                street=p.street;
            } else  if (entity instanceof Car) {
                //...
            }
            logger.trace("Entity name: {}", street);
        }
    
    }
    

    如果不是这种情况,那么您将不得不使用反射:

    try {
       Field field = entity.getClass().getField("street");
       street = (String) field.get(entity);
    } catch (NoSuchFieldException ex) {
      //This entity has no street field
    }
    

    【讨论】:

      【解决方案3】:

      不,您不可能访问定义在类方法中的局部变量。编译器不保留名称。

      如果属性/字段被定义为类级别属性,那么您可以按照@Landei 提到的方式访问它们。

      【讨论】:

        【解决方案4】:

        您可以使用反射来检查该字段是否存在:

        public void doSomething(E entity) {
            String street = "";
            Class<?> entityClass = entity.getClass();
            // getDeclaredField would allow to see non-public members
            Field streetField = entityClass.getField("street");
            // you should check the type of the filed here !
            logger.trace("Entity name: {}", streetField.get());
        }
        

        更多详情请见http://docs.oracle.com/javase/tutorial/reflect/index.html

        然而,使用带有反射的泛型对我来说似乎是一种气味,我建议重新考虑您的设计以确保没有其他方法!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-03
          • 1970-01-01
          • 1970-01-01
          • 2012-02-14
          相关资源
          最近更新 更多