如何为Fields创建功能接口实现? [英] How can I create a Functional interface implementation for Fields?
问题描述
在类 Animal
中考虑字段 weight
。我希望能够创建一个 getter 和 setter 功能接口对象来操作这个字段。
Consider a field weight
in class Animal
. I want to be able to create a getter and setter functional interface objects for manipulating this field.
class Animal {
int weight;
}
我目前的方法与方法类似:
My current approach is similar to one used for methods:
public static Supplier getter(Object obj, Class<?> cls, Field f) throws Exception {
boolean isstatic = Modifier.isStatic(f.getModifiers());
MethodType sSig = MethodType.methodType(f.getType());
Class<?> dCls = Supplier.class;
MethodType dSig = MethodType.methodType(Object.class);
String dMthd = "get";
MethodType dType = isstatic? MethodType.methodType(dCls) : MethodType.methodType(dCls, cls);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle fctry = LambdaMetafactory.metafactory(lookup, dMthd, dType, dSig, lookup.unreflectGetter(f), sSig).getTarget();
fctry = !isstatic && obj!=null? fctry.bindTo(obj) : fctry;
return (Supplier)fctry.invoke();
}
但这会产生以下错误:
java.lang.invoke.LambdaConversionException: Unsupported MethodHandle kind: getField x.Animal.weight:()int
更新
我正在尝试创建一个类 ObjectMap
实现接口地图
,它基本上尝试表示 对象 地图
,其中对象可以是任何类型。当前正在使用 Field.get()
和 Field.set()
来操作中的字段get()
和 put()
方法,并使用上述方法创建供应商
和 Consumer
用于调用 getter 和 setter 方法的对象。我想知道我是否可以将两个单独的方法合并为一个。
I am trying to create a class ObjectMap
implementing interface Map
, which basically tries to represent an object as a Map
, where the object can be of any type. Was currently using Field.get()
and Field.set()
for manipulating fields in get()
and put()
methods, and using above mentioned approach to create Supplier
and Consumer
objects for invoking getter and setter methods. I was wondering if i could merge the two separate methods into one.
示例类可以用作 Map
通过 ObjectMap
:
public class ThisCanBeAnything {
/* fields */
public String normalField;
private int hiddenFiled;
private String hiddenReadonlyField;
/* getters and setters */
public int hiddenField() {
return hiddenField;
}
public void hiddenField(int v) {
System.out.println("set: hiddenField="+v);
hiddenField = v;
}
public String hiddenReadonlyField() {
return hiddenReadonlyField;
}
}
以下是预期用途:
Object o = new ThisCanBeAnything();
Map m = new ObjectMap(o);
m.put("normalField", "Normal");
System.out.println(m.get("normalField")); // Normal
m.put("hiddenField", 1); // set: hiddenField=1
System.out.println(m.get("hiddenField")); // 1
m.put("hiddenReadonlyField", 1); // does not do anything
System.out.println(m.get("hiddenReadonlyField")); // null
推荐答案
你可以直接写lambda,你根本不需要 LambdaMetafactory
:
You can directly write the lambda, you don't need the LambdaMetafactory
at all:
public static Supplier getter(Object obj, Field f) {
return () -> {
try {
return f.get(obj);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
};
}
或运行时类型安全版本:
Or a runtime-typesafe version:
public static <T> Supplier<T> getter(Object obj, Class<T> fieldClass, Field f) {
if (!fieldClass.isAssignableFrom(f.getType()))
throw new RuntimeException("Field is not of expected type");
return () -> {
try {
return (T) f.get(obj);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
};
}
例如:
private class X {
public int a;
}
@Test
public void supplier_getter_test() throws NoSuchFieldException {
X a = new X();
a.a = 5;
Supplier<Integer> sup = getter(a, int.class, X.class.getField("a"));
assertEquals(5, sup.get().intValue());
}
这篇关于如何为Fields创建功能接口实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!