4

AbstractMethodError从调用由调用定义的方法中得到一个LambdaMetafactory#metafactory()。我无法弄清楚我做错了什么导致它。我查看了很多LambdaMetafactory#metafactory()在线使用的示例,但没有找到与我正在尝试做的完全匹配的任何示例。

这是运行附加代码的[整个]输出:

Result[0] = "version 1"
Result[0] = "1"
Exception in thread "main" java.lang.AbstractMethodError
    at junk.LMTest.invokeMaker(LMTest.java:52)
    at junk.LMTest.main(LMTest.java:65)

我要做的是创建一个具有单个字段的类,该字段可以直接分配一个 lambda,或者通过查找类名和方法名来分配。双重性的原因是抽象出指定被调用方法的方式(直接在代码中指定,或在配置文件中指定)。

附加代码定义了一个功能接口,该接口ListMaker具有一个从对象的字符串表示生成单元素列表的方法。它包含一个listify实现与接口方法签名匹配的函数的静态方法,并将用于示例的直接设置方法部分。

这是代码:

package junk;

import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class LMTest
{

  @FunctionalInterface
  public interface ListMaker
  {
    public List<String> makeList(Object obj);
  }

  private ListMaker maker;

  public static List<String> listify(Object obj)
  {
    List<String> l = new ArrayList<>();
    l.add(obj.toString());
    return l;
  }

  public void setMaker(ListMaker maker)
  {
    this.maker = maker;
  }

  public void setMaker(String className, String methodName)
      throws Throwable
  {
    Method m = Class.forName(className).getDeclaredMethod(methodName, Object.class);
    MethodHandles.Lookup l = MethodHandles.lookup();
    MethodHandle handle = l.unreflect(m);
    CallSite cs = LambdaMetafactory.metafactory(l,
                                                "makeList",
                                                MethodType.methodType(ListMaker.class),
                                                handle.type().generic(),
                                                handle,
                                                handle.type());
    maker = (ListMaker)cs.getTarget().invoke();
  }

  public void invokeMaker(Object obj)
  {
    String result0 = maker.makeList(obj).get(0);
    System.out.println("Result[0] = \"" + result0 + "\"");
  }

  public static void main(String[] args)
      throws Throwable
  {
    LMTest lmt = new LMTest();
    lmt.setMaker(LMTest::listify);
    lmt.invokeMaker("version 1");
    lmt.invokeMaker(1);
    //
    lmt.setMaker("junk.LMTest", "listify");
    lmt.invokeMaker("version 2");
    lmt.invokeMaker(2);
  }
}

我已经能够理解我在网上找到的类似示例,但它们都是最终结果;我无法找到任何足以描述最终结果的内容(至少对我而言),帮助我找出我做错了什么。

4

1 回答 1

3

我认为错误是.generic()handle.type().generic()您对LambdaMetafactory.metafactory().

我拿走了你的代码,删除了对的调用.generic(),你的代码运行成功。

方法的文档generic()说,此方法将MethodType调用它的所有类型转换为 Object。 h.type()是接受对象并返回列表h.type().generic()的方法的签名,而 是接受对象并返回对象的方法的签名。

我不认为该generic()方法与泛型类型有任何关系。请不要仅仅因为函数式接口中的方法有一个泛型类型的参数就觉得你必须使用它。我承认我以前没有遇到过这种方法,但我认为它的名称令人困惑。

于 2015-05-30T13:57:58.727 回答