我在JAVA中有一个枚举和POJO类。在枚举类中,每个枚举值都与POJO类的变量匹配...然后,我想在两个类之间创建一个关系。
枚举类别:
10
POJO类:
public enum MyEnum
{
FIELD1,
FIELD2,
FIELD3,
...
}
然后,当我尝试匹配两个类的这些字段时,我实现了如下代码:
public class MyPojo
{
private String field1;
private String field2_not_ref;
private String field3;
...
}
我认为这不是一个好的/明确的解决方案。有什么建议吗?
答案 0 :(得分:5)
与在枚举上定义方法相比,为了避免反射(该过程可能较慢并且使事情更简洁),您可以创建一个枚举,其枚举的字段使用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;
}
}
然后您可以通过以下方式调用它:
public static void main(String[] args) {
MyPojo myPojo = new MyPojo("f1", "f2", "f3");
System.out.println(MyEnum.FIELD2.getGetField().apply(myPojo));
}
如果不想通过Function
方法将其用作apply
变量,则可以在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); }
}
并像这样调用它:
public static void main(String[] args) {
MyPojo myPojo = new MyPojo("f1", "f2", "f3");
System.out.println(MyEnum.FIELD2.getFieldFromMyPojo(myPojo));
}
为简洁起见,省略了字母和二传手。
答案 1 :(得分:2)
还有另一种方法:
在enum中定义一个抽象方法,并为每个enum字段覆盖:
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
定义字段的获取方法:
还定义方法matchMethod
的方式来处理对枚举的责任(如果您愿意,这不是强制性的,因为枚举可以自行解决该字段)。
public class MyPojo {
private String field1;
private String field2;
private String field3;
public MyPojo(String field1, String field2, String field3) {
this.field1 = field1;
this.field2 = field2;
this.field3 = field3;
}
public String getField1() {
return field1;
}
public String getField2() {
return field2;
}
public String getField3() {
return field3;
}
public String matchMethod(MyEnum myEnum) {
return myEnum.getFromPojo(this);
}
}
现在,在“主要”方法中,您可以使用以下方法:
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
答案 2 :(得分:2)
您可以使用反射。这是一个示例:
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);
}
使用反射有一些缺点,例如类型安全性或可追溯性,但是在这种情况下,我认为我会选择此选项。
另一个,更灵活的选择是将反射与自定义注释结合使用:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyEnumRef {
MyEnum value();
}
和通用界面:
public interface Pojo {
}
现在,声明新的Pojo
变得更加简单明了,并且可读性也越来越强(至少对于某些人而言)。在实际的映射(配置)完成的地方也很明显。
public class MyPojo implements Pojo {
@MyEnumRef(MyEnum.FIELD1)
private String field1;
@MyEnumRef(MyEnum.FIELD2)
private String field2;
@MyEnumRef(MyEnum.FIELD3)
private String field3;
}
public class MyOtherPojo implements Pojo {
@MyEnumRef(MyEnum.FIELD1)
private String field1;
@MyEnumRef(MyEnum.FIELD2)
private String field2;
}
一种简单的方法来统治所有人:
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
的哪种实现都无关紧要。添加新的Pojos时没有开销。示例:
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")));
}
答案 3 :(得分:1)
此解决方案仅适用于static
字段,因为枚举始终为static
!
我可以想象的一种方法是:
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),
...
}
答案 4 :(得分:1)
这是另一种方法,它确实具有一个间接级别(注册),但没有修改枚举。
这需要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));
}
}
此打印:
a
b
c
x
y
z
答案 5 :(得分:0)
有多种选择(包括使用reflection),但是在简单的情况下,这些字段都是相同的类型(此处为fn capitalize_first(s: &str) -> String {
let mut chars = s.chars();
chars
.next()
.map(|first_letter| first_letter.to_uppercase())
.into_iter()
.flatten()
.chain(chars)
.collect()
}
),我的建议是存储感兴趣的值改为使用EnumMap
:
transcribe.start_transcription_job(
TranscriptionJobName=job_name,
Media={'MediaFileUri': job_uri},
MediaFormat='mp3',
LanguageCode='en-US'
)