按名称实例化 Java lambda 函数

2024-03-29

我想在 Java 8 中创建一个 lambda 函数,获取它的类名,然后从它的类名再次实例化该函数。

这就是我尝试的:

import java.util.function.Consumer;

public class SimpleLambda
{
    public static void call(String aLambdaClassName, String aArg) throws Exception
    {
        Class<Consumer<String>> lClass = (Class<Consumer<String>>) Class.forName(aLambdaClassName);
        Consumer<String> newlamba = lClass.newInstance();
        newlamba.accept(aArg);
    }

    public static void main(String[] args) throws Exception
    {
        {
            // Attempt with a static method as lambda
            Consumer<String> lambda = Host::action;
            String classname = lambda.getClass().getName();
            call(classname, "Hello world");
        }

        {
            // Attempt with a locally defined lambda
            Consumer<String> lambda = (s) -> { System.out.println(s); };
            String classname = lambda.getClass().getName();
            call(classname, "Hello world");
        }
    }
}

class Host {
    public static void action(String aMessage) {
        System.out.println(aMessage);
    }
}

但是,使用此代码(在两种变体中,使用静态方法引用并使用本地声明的 lambda),我得到一个异常:

Exception in thread "main" java.lang.ClassNotFoundException: mypackage.SimpleLambda$$Lambda$1/471910020
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at mypackage.SimpleLambda.main(SimpleLambda.java:12)

我本以为我至少可以重新实例化静态方法引用...不,显然不能。

我一直在 Groovy Closures 中使用类似的方法,效果很好。那么我只是对 Java 8 lambda 做错了什么,还是无法通过名称实例化 lambda?我在网上发现了一些提示,表明 lambda 可以被序列化(反序列化),因此我希望也可以通过名称实例化它们。


嗯,使用“匿名类”是 Oracle 的 JRE/OpenJDK 的一个特殊属性,根本无法通过名称来访问它。但即使没有这个,也没有理由这样做:

  • Class.forName(String)尝试通过调用者的方法解析该类ClassLoader。因此,即使 lambda 表达式是使用普通类实现的,如果通过不同的类加载也无法访问ClassLoader
  • Class.newInstance()仅当有一个时才有效public无参数构造函数。你不能假设有一个无参构造函数,也不能假设它是public
  • 整个函数的逻辑必须驻留在单个类中的假设是错误的。一个反例是java.lang.reflect.Proxy这会产生interface实现委托给InvocationHandler。尝试通过其类名重新实例化此类代理将会失败,因为您需要传递实际的代理InvocationHandler代理构造函数的实例。原则上,JRE 特定的 lambda 表达式实现可以使用类似的模式

考虑到上述几点,应该清楚的是,您不能说它通常适用于内部类。为此,您必须满足很多限制。


关于序列化,它适用于可序列化的 lambda 表达式,因为持久化形式与运行时实现类完全分离,如这个答案中描述的 https://stackoverflow.com/a/29625025/2711488。因此,生成的类的名称不包含在序列化形式中,并且反序列化端可能具有完全不同的运行时实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

按名称实例化 Java lambda 函数 的相关文章

随机推荐

  • 创建对象时抛出异常

    执行catch语句时是否会创建异常对象 例如 catch ArithmeticException someObject 该对象是否不必显式创建为实例 有两件事创建异常的实例第二抛出异常 创建异常的实例例如 看起来像创建类的任何实例NullP
  • Ansible 中的角色和任务(和标签)有什么区别?

    我发现自己很困惑roles and tasks每时每刻 我知道标签是标记单个项目的一种方式 但我很困惑如何使用它们 假设我必须执行以下操作 Users Create a user named deploy Add ssh key for d
  • 如何解组嵌套的未知字段

    我分叉了一个很棒的项目here https github com sridharv reddit go blob master types go 并且刚刚把它弄得一团糟 学习了一些Go 我无法弄清楚的问题是有关自定义解组的一些事情 如果您看
  • 如何从作业中设置环境变量并在詹金斯的下一个作业中使用它?

    我想要一份设置环境变量的工作 并在接下来的所有工作中使用这些环境变量 如何通过 Jenkins 设置环境变量 从技术上讲 您无法将环境变量从一个作业传递到下一个作业 而且我不知道有一个插件可以开箱即用地执行此操作 不过有一个技巧 这个想法是
  • 如何使用多个类的序列化来实现备份和恢复?

    我正在尝试序列化存储在 JTable 中的对象 名称和注释 我希望能够将此信息保存到文件中 并且当我加载程序时 该信息应加载到 JTable 中 当我单击备份按钮时 正在创建一个文件 但没有存储任何数据 有人可以指导我正确的方向并告诉我我做
  • 将 Python Opencv 图像(numpy 数组)转换为 PyQt QPixmap 图像

    我正在尝试将 python opencv 图像转换为 QPixmap 我按照说明进行操作页面链接 http russellj tumblr com post 44845729156 convert python opencv image n
  • 编辑中的字段唯一(已采用)?

    当我编辑用户时 我遇到验证问题 因此 当我编辑时 我收到消息称该名称已被占用 我怎样才能解决这个问题 因为该名称属于该用户 所以我需要再次更改名称 以便我可以编辑我的用户 if user gt business user this gt v
  • 如何编辑 Visual Studio Code 的默认深色主题?

    我使用的是 Windows 7 64 位 有没有办法在 Visual Studio Code 中编辑默认的深色主题 在 USERPROFILE vscode文件夹中只有扩展中的主题 而在安装路径中 我使用默认值 C Program File
  • Windows Azure /Windows Server 2008 R2 中的 NAudio

    我在用NAudio http naudio codeplex com 将几个 mp3 文件合并在一起以形成 Windows Azure 产品 它在开发环境中工作正常 但一旦我将其上传到 Azure 我就会收到 无驱动器调用 acmForma
  • Java 中的 \x 转义?

    我想知道 Java 中是否有类似 C 中的十六进制 x 转义 例如 char helloworld x48 x45 x4C x4C x4F x20 x57 x47 x52 x4C x44 printf s helloworld 从目前看来
  • Vaadin:如何将 META-INF/服务添加到战争中?

    我有一个 Vaadin 7 maven Web 项目 其中有一些注释可以在其上创建服务定义META INF services 我将其添加到 pom 中 以便处理注释
  • GCP Pub/Sub,如果已经有活动订阅,您可以在新订阅上重播旧消息吗

    在 GCP Pub Sub 中 我有一个主题和一个Subscription1并已开始发布消息 我可以添加另一个订阅吗Subscription2并重播之前发布的旧消息Subscription2被创造了 它会允许吗 卡夫卡允许 在什么时候我会失
  • C++ 模板正式排序规则

    我很难理解 D Vandevoorde 和 N M Josuttis 所著的 C 模板完整指南 一书第 12 章中描述的正式排序规则的工作原理 在本书第 188 页 作者给出了以下场景 用于确定两个可行的函数模板中哪一个更专业 从这两个模板
  • Flutter - 获取 SHA-1 证书 - Android Studio 3.2.1

    我正在尝试检索我的 Flutter 项目的 SHA 1 指纹证书 这通常可以通过进入 Android Studio 右侧的 Gradle 面板并单击signingReport 然而问题是 在 Flutter 中 它根本不显示 Gradle
  • Laravel 可以处理高流量应用程序吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在开发一个 PHP MySQL 社交网络项目 该项目将包含许多模块 部分 包括 用户系统 权限 配置文件 设置等 stackoverflow
  • Tomcat 9 的 Maven 插件

    除了 tomcat7 maven plugin 之外 我没有找到任何 tomcat maven plugin 我可以将其与 apache tomcat 9 0 0 M15 一起使用吗 您可以使用该插件部署到单独运行的 tomcat 9 Th
  • 自定义样式的 AlertDialog 的样式属性

    我正在尝试设计我的 AlertDialog 的样式 并且我已经能够通过样式和 xml 声明更改其中的大部分内容 但仍然存在一些问题 如何将标题栏周围的区域从黑色更改为我的自定义颜色 如何将外部背景更改为透明 阴影落在蓝色的外部部分 如何更改
  • “yes”这个程序有什么重要用途吗?

    当我第一次遇到yes nix 中的程序我想不出它有什么重要用途 这个程序是如何使用的 yes旨在自动化需要在采取行动之前确认的交互式程序 yes rm ri foo 大致相当于 rm rf foo 不同之处在于 f失败时也会继续
  • Rails 4 jQuery 与 javascript 冲突

    我正在尝试在 Rails 4 中制作一个应用程序 我正在挣扎 我正在尝试合并引导主题 但我遇到了供应商 JavaScript 和其余代码的问题 我认为问题可能与我的 application js 中的 jQuery 以及以 符号开头的供应商
  • 按名称实例化 Java lambda 函数

    我想在 Java 8 中创建一个 lambda 函数 获取它的类名 然后从它的类名再次实例化该函数 这就是我尝试的 import java util function Consumer public class SimpleLambda p