如何从实体中获取属性的名称

How to get the name of an Attribute from an Entity

我有以下实体 class:

public class Conversation { 
    private String id;
    private String ownerId;
    private Long creationDate;

    public Conversation(String id, String ownerId, Long creationDate){
        this.id = id;
        this.ownerId = ownerId;
        this.creationDate = creationDate;
    }
}

在通过外部服务的其他子模块上,每次插入时,我都会收到以下实体的映射:

public class AttributeValue {
    private Sring s; //string attribute
    private String n; //number attribute

    public String getS() {
        return this.s;
    }

    public String getN() {
        return this.n;
    }

    public AttributeValue(String s, String n){
        this.s = s;
        this.n = n;
    }
}

//Example if I insert this conversation: new Conversation("1", "2", 1623221757971)
// I recive this map:
Map<String, AttributeValue> insertStream = Map.ofEntries(
    entry("id", new AttributeValue("1", null)),
    entry("ownerId", new AttributeValue("2", null)),
    entry("creationDate", new AttributeValue(null, "1623221757971"))
);

要从地图中读取 ownerId 字段,我必须这样做:

String ownerId = insertStream.get("ownerId").getS();

我的问题是,不是必须写:insertStream.get("ownerId"),是否存在通过反射从实体 (Conversation.ownerId) 读取字段名称的任何方式? 这是因为我们要维护子模块,如果我们对实体进行更改,例如将 ownerId 更改为 ownerIdentifier,则子模块会显示编译错误或自动更改。

这是你想要的吗? <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html#getName--" rel="nofollow noreferrer">Field#getName()</a>
示例代码:

Field[] conversationFields = Conversation.class.getDeclaredFields();
String field0Name = conversationFields[0].getName();

根据使用的 JVM,field0Name 可以是 "id"。也可以使用<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getFields--" rel="nofollow noreferrer">Class#getFields()</a>,这个方法包括所有在这个class(superclass的字段中可以访问到的Field ).


另一种选择(不使用反射)是重构您的代码。

import java.util.Map;
import java.util.HashMap;

public class Conversation {
    public static String[] names = {
        "id", "ownerId", "creationDate"
    };
    private Map<String, Object> data = new HashMap<String,Object>();
    public Conversation(Object... data) {
        if(data.length!=names.length)
            throw new IllegalArgumentException("You need to pass "+names.length+" arguments!");
        for(int i=0; i<names.length; i++)
            data.put(names[i],data[i]);
    }

    public Map<String,Object> getData() { return data; }

    // You can pass "id"/"ownerId" or names[0]/names[1]
    public String getString(String key) {
        return (String)data.get(key);
    }

    // You can pass "creationDate" or names[2]
    public long getLong(String key) {
        return (long)data.get(key);
    }
}

然后您可以像以前一样创建 Conversation 个对象:

Conversation c = new Conversation("myId","myOwnerId",123456789L);

您也可以添加 public static String 字段,例如 ID="id",但更改字段的值永远不会更改字段的名称。