Java 将枚举值与类字段匹配
我在JAVA中有一个enum和POJO类。在枚举类中,每个枚举值都与POJO类的变量匹配。。。然后我想在两个类之间创建一个关系 枚举类:Java 将枚举值与类字段匹配,java,oop,java-8,enums,switch-statement,Java,Oop,Java 8,Enums,Switch Statement,我在JAVA中有一个enum和POJO类。在枚举类中,每个枚举值都与POJO类的变量匹配。。。然后我想在两个类之间创建一个关系 枚举类: public enum MyEnum { FIELD1, FIELD2, FIELD3, ... } POJO类: public class MyPojo { private String field1; private String field2_not_ref; private String field3;
public enum MyEnum
{
FIELD1,
FIELD2,
FIELD3,
...
}
POJO类:
public class MyPojo
{
private String field1;
private String field2_not_ref;
private String field3;
...
}
然后,当我尝试匹配两个类的这些字段时,我实现了如下代码:
public String matchMethod(MyEnum myenum)
{
switch(myenum)
{
case FIELD1:
return field1;
case FIELD2:
return field2_not_ref;
...
}
}
我认为这不是一个好的/明确的解决办法。有什么建议吗?有多种选择(包括使用),但在简单的情况下,如果字段都是相同类型的(这里是字符串),我的建议是将感兴趣的值存储在
类MyPojo{
私有最终EnumMap字段=新EnumMap(MyEnum.class);
公共字符串匹配方法(MyEnum MyEnum){
返回字段.get(myenum);
}
public void setField1(字符串值){
fields.put(MyEnum.FIELD1,value);//例如
}
}
此解决方案仅适用于静态
字段,因为枚举总是静态
强>
我可以想象的一种方式是:
public enum MyEnum
{
private String field;
public String getField()
{ return this.field; }
MyEnum(String field)
{
this.field = field;
}
FIELD1(field1),
FIELD2(field2),
FIELD3(field3),
...
}
如果需要,您甚至可以将其设置为通用:
public enum MyEnum<T>
{
private T field;
public T getField()
{ return this.field; }
MyEnum(T field)
{
this.field = field;
}
FIELD1(field1),
FIELD2(field2),
FIELD3(field3),
...
}
公共枚举MyEnum
{
私人T场;
公共T getField()
{返回this.field;}
髓鞘(T区)
{
this.field=字段;
}
字段1(字段1),
字段2(字段2),
字段3(字段3),
...
}
还有一种方法:
在枚举中定义抽象方法,并覆盖每个枚举字段:
public enum MyEnum {
FIELD1 {
@Override
public String getFromPojo(MyPojo myPojo) {
return myPojo.getField1();
}
},
FIELD2 {
@Override
public String getFromPojo(MyPojo myPojo) {
return myPojo.getField2();
}
},
FIELD3 {
@Override
public String getFromPojo(MyPojo myPojo) {
return myPojo.getField3();
}
};
public abstract String getFromPojo(MyPojo myPojo);
}
对于类MyPojo
为字段定义getter:
还定义方法matchMethod
,使其能够处理对枚举的责任(如果您愿意,这不是强制性的,因为枚举可以自己解析字段)
现在,在“main”方法中,您可以使用以下方法:
MyPojo p1 = new MyPojo("p1", "p2", "p3");
MyPojo p2 = new MyPojo("k1", "k2", "k3");
System.out.println(MyEnum.FIELD1.getFromPojo(p1));
System.out.println(MyEnum.FIELD2.getFromPojo(p1));
System.out.println(MyEnum.FIELD3.getFromPojo(p1));
System.out.println(MyEnum.FIELD1.getFromPojo(p2));
System.out.println(MyEnum.FIELD2.getFromPojo(p2));
System.out.println(MyEnum.FIELD3.getFromPojo(p2));
// in addition, if you've defined 'matchMethod' on POJO
System.out.println(p1.matchMethod(MyEnum.FIELD1));
System.out.println(p1.matchMethod(MyEnum.FIELD2));
System.out.println(p1.matchMethod(MyEnum.FIELD3));
System.out.println(p2.matchMethod(MyEnum.FIELD1));
System.out.println(p2.matchMethod(MyEnum.FIELD2));
System.out.println(p2.matchMethod(MyEnum.FIELD3));
这张照片是:
p1
p2
p3
k1
k2
k3
// and optionally...
p1
p2
p3
k1
k2
k3
a
b
c
x
y
z
你可以使用反射。以下是一个例子:
public String matchMethod(MyEnum myenum, Map<MyEnum, String> enumToFieldMap) throws NoSuchFieldException, IllegalAccessException {
String customFieldName = enumToFieldMap.get(myenum);
if (customFieldName == null) { // custom field name not found, use default mapping
return (String) this.getClass().getDeclaredField(myenum.name().toLowerCase()).get(this);
} // custom field name found in config
return (String) this.getClass().getDeclaredField(customFieldName).get(this);
}
public String matchMethod(MyEnum myEnum) throws NoSuchFieldException, IllegalAccessException {
return matchMethod(myEnum, Collections.EMPTY_MAP);
}
和通用接口:
public interface Pojo {
}
声明新的Pojo
(s)现在变得更简单、更清晰,也更具可读性(至少对某些人来说)。在实际映射(配置)完成的地方也很明显
一个简单的方法可以将它们全部规则化:
public String matchMethod(MyEnum myEnum, Pojo myPojo) throws IllegalAccessException {
for (Field field : myPojo.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(MyEnumRef.class) && field.getAnnotation(MyEnumRef.class).value() == myEnum) {
field.setAccessible(true);
return (String) field.get(myPojo);
}
}
return "";
}
使用哪种Pojo
实现并不重要。添加新POJO时没有开销。例如:
private void run() throws IllegalAccessException {
System.out.println(">>" + matchMethod(MyEnum.FIELD2, new MyPojo("f1", "f2", "f3")));
System.out.println(">>" + matchMethod(MyEnum.FIELD1, new MyOtherPojo("o1", "o2")));
}
为了避免反射,这可能会比在枚举上定义方法更慢,更简洁,您可以创建一个枚举,其中的字段是使用MyPojo
并返回String
的函数:
public enum MyEnum {
FIELD1(MyPojo::getField1),
FIELD2(MyPojo::getField2),
FIELD3(MyPojo::getField3);
private final Function<MyPojo, String> getField;
MyEnum(Function<MyPojo, String> getField) {
this.getField = getField;
}
}
如果您不想使用apply
方法将其用作函数
变量,可以在en enum上创建一个函数,即:
public enum MyEnum {
FIELD1(MyPojo::getField1),
FIELD2(MyPojo::getField2),
FIELD3(MyPojo::getField3);
private final Function<MyPojo, String> getField;
MyEnum(Function<MyPojo, String> getField) {
this.getField = getField;
}
String getFieldFromMyPojo(MyPojo myPojo) { return getField.apply(myPojo); }
}
为了简洁起见,省略了getter和setter。这里还有另一种方法,它有一个间接级别(注册表),但不修改枚举
这需要Java 8+,因为它使用lambda表达式:
import java.util.EnumMap;
import java.util.function.Function;
enum MyEnum {
FIELD1, FIELD2, FIELD3;
}
class MyPojo {
private String field1, field2, field3;
public MyPojo(String f1, String f2, String f3) {
this.field1 = f1;
this.field2 = f2;
this.field3 = f3;
}
private static EnumMap<MyEnum, Function<MyPojo, String>> registry = new EnumMap(MyEnum.class);
static {
registry.put(MyEnum.FIELD1, p -> p.field1);
registry.put(MyEnum.FIELD2, p -> p.field2);
registry.put(MyEnum.FIELD3, p -> p.field3);
}
public String matchMethod(MyEnum e) {
return registry.get(e).apply(this);
}
}
class Main {
public static void main(String[] args) {
MyPojo p1 = new MyPojo("a", "b", "c");
MyPojo p2 = new MyPojo("x", "y", "z");
System.out.println(p1.matchMethod(MyEnum.FIELD1));
System.out.println(p1.matchMethod(MyEnum.FIELD2));
System.out.println(p1.matchMethod(MyEnum.FIELD3));
System.out.println(p2.matchMethod(MyEnum.FIELD1));
System.out.println(p2.matchMethod(MyEnum.FIELD2));
System.out.println(p2.matchMethod(MyEnum.FIELD3));
}
}
什么时候设置字段1,2,3的值?@azro,在我的main方法中,…mymain方法(MyPojo MyPojo,MyEnum MyEnum){…对象匹配结果=MyPojo.matchMethod(MyEnum);…}我看得对吗,你希望POJO字段是可变的?或者这些字段应该是不可变的?我的意思是,在MyPojo
中更改值所应用的映射帽是否正确?@janhold,问题很清楚。我需要匹配枚举字段和POJO字段。因此,我会像这样使用它newmypojo.getFieldByEnum(myEnum)->返回匹配字段
;这与不可变/可变的事物无关。这不起作用:两个POJO可以有一个值用于FIELD1
,等等。你完全正确。这只适用于静态字段。。。。我更正了答案这看起来与SOLID Prensiple(打开以进行扩展,关闭以进行修改)和耦合内聚性不兼容?因此,从enum调用POJO类对我来说不是一个好选择。这取决于您的用例,目前MyPojo和MyEnum已经耦合:从enum中删除FIELD3,您必须更改POJO;向Pojo添加一个新字段,可能还需要更改MyEnum
。我已经尝试促进java语法功能,所有其他解决方案都将包括一个间接层:映射等等。当然,您可以选择所有可能与枚举不匹配的名称。我投票支持第二种选择,即在枚举内部使用apply。OP的全部想法不是每次都不调用MyEnum.FIELD2或其他特定的枚举类型吗?甚至@Sha提出的转换比这种方法更通用。@PiotrNiewinski你是说,问题中的整个转换比简单地编写myenum.getFieldFromMyPojo(myPojo)
?@Andronicus一点也不,我是说这可能表明OP在寻找更通用的答案,至少有matchMethod
的签名提示soHmm。“然后我想在两个类之间创建一个关系。”这让我可以自由地设计enum以了解实体。
public enum MyEnum {
FIELD1(MyPojo::getField1),
FIELD2(MyPojo::getField2),
FIELD3(MyPojo::getField3);
private final Function<MyPojo, String> getField;
MyEnum(Function<MyPojo, String> getField) {
this.getField = getField;
}
}
public static void main(String[] args) {
MyPojo myPojo = new MyPojo("f1", "f2", "f3");
System.out.println(MyEnum.FIELD2.getGetField().apply(myPojo));
}
public enum MyEnum {
FIELD1(MyPojo::getField1),
FIELD2(MyPojo::getField2),
FIELD3(MyPojo::getField3);
private final Function<MyPojo, String> getField;
MyEnum(Function<MyPojo, String> getField) {
this.getField = getField;
}
String getFieldFromMyPojo(MyPojo myPojo) { return getField.apply(myPojo); }
}
public static void main(String[] args) {
MyPojo myPojo = new MyPojo("f1", "f2", "f3");
System.out.println(MyEnum.FIELD2.getFieldFromMyPojo(myPojo));
}
import java.util.EnumMap;
import java.util.function.Function;
enum MyEnum {
FIELD1, FIELD2, FIELD3;
}
class MyPojo {
private String field1, field2, field3;
public MyPojo(String f1, String f2, String f3) {
this.field1 = f1;
this.field2 = f2;
this.field3 = f3;
}
private static EnumMap<MyEnum, Function<MyPojo, String>> registry = new EnumMap(MyEnum.class);
static {
registry.put(MyEnum.FIELD1, p -> p.field1);
registry.put(MyEnum.FIELD2, p -> p.field2);
registry.put(MyEnum.FIELD3, p -> p.field3);
}
public String matchMethod(MyEnum e) {
return registry.get(e).apply(this);
}
}
class Main {
public static void main(String[] args) {
MyPojo p1 = new MyPojo("a", "b", "c");
MyPojo p2 = new MyPojo("x", "y", "z");
System.out.println(p1.matchMethod(MyEnum.FIELD1));
System.out.println(p1.matchMethod(MyEnum.FIELD2));
System.out.println(p1.matchMethod(MyEnum.FIELD3));
System.out.println(p2.matchMethod(MyEnum.FIELD1));
System.out.println(p2.matchMethod(MyEnum.FIELD2));
System.out.println(p2.matchMethod(MyEnum.FIELD3));
}
}
a
b
c
x
y
z