Java中获取类字段名

San*_*isy 1 java spring java-module java-14

public class Product{
    private String id;
    private String name;
    private String description;
    // Getters and setters..
}
Run Code Online (Sandbox Code Playgroud)

从上面的类中,我想在运行时获取描述的字段名称:

Query query = new Query();
        if (productSearchCriteria.getDescription().isPresent()) {
            query.addCriteria(Criteria.where("description").is(productSearchCriteria.getDescription().get()));
        }
Run Code Online (Sandbox Code Playgroud)

目前,我已经对名称进行了硬编码,但它应该是动态的,因为如果有人重命名或更改属性名称,这将不起作用。

环顾四周,我发现了一个reflection-util库。

 String numberProperty = PropertyUtils.getPropertyName(Product.class, Product::getDescription);
Run Code Online (Sandbox Code Playgroud)

这给了我一个例外:

Caused by: java.lang.ClassCastException: class domain.Product$ByteBuddy$QIcFk1aK cannot be cast to class domain.Product (domain.Product$ByteBuddy$QIcFk1aK is in unnamed module of loader net.bytebuddy.dynamic.loading.ByteArrayClassLoader @33943b71; domain.Product is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @5be4b0e6)
    at de.cronn.reflection.util.PropertyUtils.findMethodByGetter(PropertyUtils.java:322) ~[reflection-util-2.6.0.jar:na]
    at de.cronn.reflection.util.PropertyDescriptorCache.lambda$getMethod$4(PropertyDescriptorCache.java:178) ~[reflection-util-2.6.0.jar:na]
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]
    at de.cronn.reflection.util.PropertyDescriptorCache.getMethod(PropertyDescriptorCache.java:178) ~[reflection-util-2.6.0.jar:na]
    at de.cronn.reflection.util.PropertyUtils.getMethod(PropertyUtils.java:315) ~[reflection-util-2.6.0.jar:na]
    at de.cronn.reflection.util.PropertyUtils.getPropertyDescriptor(PropertyUtils.java:282) ~[reflection-util-2.6.0.jar:na]
    at de.cronn.reflection.util.PropertyUtils.getPropertyName(PropertyUtils.java:290) ~[reflection-util-2.6.0.jar:na]
    at fete.bird.fetebirdproduct.common.querybuilder.QueryBuilder.BuildQuery(QueryBuilder.java:24) ~[main/:na]
    at fete.bird.fetebirdproduct.service.consumer.ProductListener.GetProducts(ProductListener.java:56) ~[main/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
    at  ... 9 common frames omitted
Run Code Online (Sandbox Code Playgroud)

我正在使用 JDK 14。我知道有一个 Java 反射 API。我无法对字段名称进行硬编码。

有什么解决办法吗?

Geo*_*rge 7

您可以尝试使用lombok生成字段名称作为常量变量。

https://projectlombok.org/features/experimental/FieldNameConstants

@Data
@FieldNameConstants
public class Product{
    private String id;
    private String name;
    private String description;
}
Run Code Online (Sandbox Code Playgroud)

这将在编译时生成:

public class Product {
    private String id;
    private String name;
    private String description;
  
  public static final class Fields {
    public static final String id = "id";
    public static final String name = "name";
    public static final String description = "description";
  }
  
  // getters and setters
}
Run Code Online (Sandbox Code Playgroud)

引用看起来像这样:

Query query = new Query();
if (productSearchCriteria.getDescription().isPresent()) {
    query.addCriteria(Criteria.where(Product.Fields.description).is(productSearchCriteria.getDescription().get()));
}
Run Code Online (Sandbox Code Playgroud)

这样做的另一个好处是,如果您决定出于某种原因更改字段名称,则会导致编译时错误,并在运行时尽早捕获它。

不需要运行时反射恶作剧。