如何转换从模块返回的对象

2023-12-19

我尝试ModuleLayer使用 JDK 11,我创建了两个模块Implementation and Model。考虑Implementation模块提供了一个方法,该方法返回一个类型的对象Foo, 班上Foo定义于Model module.

所以模块Implementation requires Model;和模块Model导出其所有名称空间。

我正在创建一个单独的应用程序Configuration解析两个模块并创建ModuleLayer以及。通过使用layer.findLoader("Implementation").loadClass()我已经加载了一个类Implementation模块并使用调用静态方法method.invoke(null, "test");它返回一个Object.

现在我不明白,我应该如何将这个对象转换为Foo?我无法使用(Foo) obj因为罐子里的Model模块不在类路径上。即使我这么说,最终也会出现例外

Caused by: java.lang.ClassCastException: class com.test.model.Foo cannot be cast to class com.test.model.Foo (com.test.model.Foo is in module Model of loader jdk.internal.loader.Loader @e9b78b0; com.test.model.Foo is in unnamed module of loader com.company.container.internal.Interpreters$ClassLoaders$$anon$1 @45815ffc)

Object provider=null;
try
{
   var path = Path.of(Core.getConfiguration().getBasePath().getPath() ,"\\model\\lib\\EC");
   ModuleFinder finder = ModuleFinder.of(path);
   var parent = ModuleLayer.boot();
   Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("Implementation"));
   ClassLoader scl = this.getClass().getClassLoader(); // intentionally using this class's loader  
   ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
   var cl = layer.findLoader("Implementation");
   Class<?> classTest = cl.loadClass("com.test.AutoConfiguration");
   var method = classSendMailFromX.getMethod("getProvider", String.class);
   provider = method.invoke(null, "test");
}
catch (Exception e) {
   throw new CoreException(e);
}
if(provider == null)
{
   throw new Exception("provider cannot be empty");
}

var myProvider = (Foo) provider; // This line compiles but calls fails at runtime if I put `Model` module jar on classpath

我理解原因,类路径中的任何 jar (即使它是一个模块)都将被视为未命名模块。但是,为什么我无法施放它?有什么办法可以做到吗?


@Holger 的评论指出了问题:Foo isn't Foo一旦它们都被不同的类/模块加载器加载。

让我概述两种不同的方法:

解决方案一:模块方式

这里的目标是上课Foo仅加载一次。 为了实现这一点,具有上述代码的应用程序也应该位于一个模块中,并且需要Model:

module App {
    requires Model;
}

为了使这项工作顺利进行,您还必须避免Model通过所提供的代码第二次加载。这可以通过 (a) 来实现not将其放入"\\model\\lib\\EC"。或者通过 (b) 改变顺序ModuleFinders in Configuration.resolve():

Configuration cf = parent.configuration().resolve(ModuleFinder.of(), finder. Set.of("Implementation"));

这边走Implementation将使用的版本Model存在于调用代码的模块路径中并且不通过加载它finder.

解决方案 2:使用代理

这需要Foo成为一个接口。

你可以有一个方法proxyOf看起来像这样:

    private Foo proxyOf(Object result) {
        InvocationHandler handler = (proxy, method, args) -> {
            Method delegate = result.getClass().getMethod(method.getName(), method.getParameterTypes());
            return delegate.invoke(result, args);
        };
        return (Foo) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{ Foo.class }, handler);
    }

这样你就可以有两个版本Foo。您只需确保应用程序代码实际上被允许访问方法delegate。所以它(以及包含的实现类)必须是public否则您将需要额外的delegate.setAccessible(true);在调用它之前。如果应用程序位于模块内(如解决方案 1),则包delegate必须通过opens clause:

module Implementation {
    requires transitive Model;
    exports org.example.impl;
    opens org.example.impl;
}

请注意,有一个主要陷阱在代理解决方案中:只要您传递 JRE 的类型,它就可以正常工作,但只要您传递自己的类型,它就可以正常工作method.getParameterTypes()将返回错误的类型,导致NoSuchMethodException。即使您设法获得正确的类型,您也需要传递该类型的代理。那么这一切都会得到really复杂,你最终会得到自己的小“来回代理”框架。

最后的笔记

不幸的是你没有描述你的内容actually想要实现。所以我们无法知道你想用它解决什么问题以及为什么需要上面的代码。老实说,对我来说,你的代码可以由其他人维护似乎相当困难。也许你可以通过使用来实现同样的事情ServiceLoader https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html?

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

如何转换从模块返回的对象 的相关文章

  • Java 中等效的并行扩展

    我在 Net 开发中使用并行扩展有一些经验 但我正在考虑在 Java 中做一些工作 这些工作将受益于易于使用的并行库 JVM 是否提供任何与并行扩展类似的工具 您应该熟悉java util concurrent http java sun
  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will

随机推荐

  • jQuery循环插件如何添加活动类

    例子 http jsfiddle net kuTLf http jsfiddle net kuTLf 代码如下所示 div div class pics div div img src http cloud github com downl
  • React-Router - 路由更改时的路由重新渲染组件

    请在标记为重复之前正确阅读本文 我向您保证 我已经阅读并尝试了大家在 stackoverflow 和 github 上针对此问题提出的所有建议 我的应用程序中有一条路线 如下所示 div div
  • 在 Linux 上设置 git 私有 SSH 密钥的自定义路径

    我正在尝试在 Linux 上设置 git 客户端 我将私钥上传到计算机 我知道我应该将其放在 ssh 中 但我无权访问该文件夹 我如何告诉 git 在其他地方寻找私钥 您可以使用ssh 配置文件 http unixhelp ed ac uk
  • 将使用 jq 解析的数组分配给 Bash 脚本数组

    我用 jq 解析了一个 json 文件 如下所示 cat test json jq logs jq jq id jq s 它返回一个像这样的数组 34 235 436 546 使用 bash 脚本我描述了一个数组 declare a msg
  • Jenkinsfile 访问 aws 凭证

    我正在尝试使用 jenkins 管道中的以下内容访问存储在 Jenkins 中的 AWS 凭证 Jenkinsfile steps withCredentials usernamePassword credentialsId eb1092d
  • AchartEngine简单动画

    是否可以使用 achartengine 库来制作它 以便在绘制图表时使其看起来像动画一样 就像柱形图的情况一样 柱形图是从屏幕底部缓慢向上移动的 您可以拥有动态图表 这意味着您可以在运行时添加数据 然后更新图表 但您不能在 AChartEn
  • 如何使用 spacy 的词形还原器将单词转化为基本形式

    我是 spacy 的新手 我想使用它的 lemmatizer 函数 但我不知道如何使用它 就像我进入单词字符串一样 它将返回具有单词基本形式的字符串 例子 单词 gt 单词 做了 gt 做 谢谢 之前的答案很复杂 无法编辑 所以这里是一个更
  • 无法读取 VR 路径注册表 - Selenium Webdriver

    我正在尝试使用 Selenium 和 java 执行测试用例 但页面未完全加载 并且我在 eclipse 控制台中收到此消息 无法读取 VR 路径注册表 这个消息是什么意思 这是代码 FirefoxDriver driver new Fir
  • UITableView reloadData - 如何停止闪烁

    我有 UITableView 闪烁的问题 我有一个hidden我想在向用户显示之前刷新 UITableView 这样做会导致表视图在再次隐藏之前非常短暂地显示在所有其他子视图之上 即使这样的代码也没有帮助 self tableView hi
  • 如何在 Chrome 中显示图像的替代文本

    来源无效的图像在 Firefox 中显示替代文本 但在 Chrome 中不会显示 除非调整图像的宽度 img height 90 width 90 src http www google com intl en ALL images log
  • 根据参数值返回不同类型的通用函数

    我有一个保存寄存器的结构 我想要我的read register函数返回一个u8 for Register V0 and Register V1 but a u16 for Register V2 and Register V3 我不确定如何
  • 在 RowDataBound 上添加 CSS 类

    我正在尝试将 CSS 类附加到 RowDataBound 上的一行 我正在针对 GridView 使用交替 css 类属性 因此我假设这适用于 RowDataBound 如果您以编程方式将 CSS 类分配给 RowDataBound 事件中
  • 为什么encode_base64给我TypeError:预期的类似字节的对象,而不是NoneType

    我有一个错误 TypeError 预期类似字节的对象 而不是 NoneType 错误源自 encoders encode base64 eml atch 第 56 行 import smtplib from email mime multi
  • 使用 CSS 垂直居中多个框

    我需要将多个不同高度的盒子垂直居中 我不知道盒子的高度 因为它们是可变文本 我怎样才能用 CSS 做到这一点 无需使用 td 和 valign 尝试过display table cell但好像不兼容IE 下图是设计图 便利贴是浏览器窗口 删
  • Powershell Invoke-Sqlcmd 捕获详细输出

    我正在尝试捕获 Powershell 中 Invoke Sqlcmd 的详细输出 任何人有任何想法可以做到这一点 i e Invoke Sqlcmd Query PRINT Hello World ServerInstance Server
  • 情节上相当于 pd.DataFrame.hist

    我正在寻找一种模仿的方法hist的方法pandas DataFrame情节地使用 这是一个使用的示例hist method import seaborn as sns import matplotlib pyplot as plt load
  • 使用 QWebPage 抓取多个 url

    我正在使用 Qt 的 QWebPage 来呈现一个使用 javascript 动态更新其内容的页面 因此仅下载页面静态版本的库 例如 urllib2 将无法工作 我的问题是 当我渲染第二页时 大约 99 的情况下程序都会崩溃 其他时候 它会
  • SQL Server Reporting Services - 设置多值报表参数的默认值

    我在 SSRS 中有一份报告 我使用的参数之一是城市 用户可以从城市列表中进行选择 以提取该位置或多个位置的报告 我的数据集只是从 tblCities 中选择 当我运行报告时 我确实看到选项之一是 全选 但是 我想知道 有没有办法可以将此
  • 如何将 Supervisor + Django + Celery 与多个队列和 Worker 一起使用?

    我正在使用 Celery Django Supervisord 并且尝试通过创建 3 个不同的队列来设置 优先级 如建议的那样 https stackoverflow com a 15827160 54872 https stackover
  • 如何转换从模块返回的对象

    我尝试ModuleLayer使用 JDK 11 我创建了两个模块Implementation and Model 考虑Implementation模块提供了一个方法 该方法返回一个类型的对象Foo 班上Foo定义于Model module