如何为Fields创建功能接口实现? [英] How can I create a Functional interface implementation for Fields?

查看:101
本文介绍了如何为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆