在Java9中,如果我不知道它的模块,我怎么能反思地加载一个类?

Rob*_*tos 6 java reflection java-9

假设我有一个给出一个众所周知的包名和类的应用程序,我需要反射性地加载该类并从中调用一些方法.假设这个类在另一个java jar("库")中可用.

到目前为止,在java 9之前,由于类路径中的所有类都可用,因此可以直接实现此目的.

但是,对于Java 9,如果应用程序"module"不需要"library"包,则无法访问库类.

如何使用模块化罐子实现相同的行为?

例:

这是我的申请:

// This is defined in ReflectionApp.jar
// ReflectionApp
// ??? src
//     ??? module-info.java
//     ??? org
//         ??? reflection
//             ??? app
//                 ??? ReflectionApp.java
//
package org.reflection.app;

import java.lang.reflect.Method;

public class ReflectionApp {
    private static final String PACKAGE = "org.reflection.lib";
    private static final String CLASS = "ReflectiveClass";
    private static final String METHOD = "doSomeWork";

    public static void main(String[] args) throws Exception {

        // This will not work using java9
        Class<?> klass = Class.forName(String.format("%s.%s", PACKAGE, CLASS));
        Object obj = klass.getDeclaredConstructor().newInstance();
        Method meth = klass.getDeclaredMethod(METHOD);
        meth.invoke(obj);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的图书馆

// This is defined in ReflectionLib.jar
// ReflectionLib
// ??? src
//     ??? module-info.java
//     ??? org
//         ??? reflection
//             ??? lib
//                 ??? ReflectiveClass.java
//
package org.reflection.lib;

public class ReflectiveClass {

    public void doSomeWork() {
        System.out.println("::: Doing some work!");
    }
}
Run Code Online (Sandbox Code Playgroud)

目前,如果我尝试这样调用它(假设所有jar都在lib目录中创建并可用):

java --module-path lib -m ReflectionApp/org.reflection.app.ReflectionApp

然后我得到了 Exception in thread "main" java.lang.ClassNotFoundException: org.reflection.lib.ReflectiveClass

---解决方案---

感谢@Nicolai,我能够通过--add-modules在命令中添加参数来使其运行.

?  java --module-path lib --add-modules ReflectionLib -m ReflectionApp/org.reflection.app.ReflectionApp
::: Doing some work!
Run Code Online (Sandbox Code Playgroud)

Nic*_*lai 6

很多方法可以使反射工作,但没有一种方法像模块系统之前的"它只是工作"一样直截了当.让我根据你的具体问题缩小范围.

但在此之前,您必须确保模块实际上将其放入模块图中.如果初始模块不能传递它,则可以使用--add-modules library它将其添加到图形中.

包导出

您写道"如果应用程序'模块'不需要'库'包,则无法访问库类".假设你的意思是模块而不是,这是真的,但在这里不适用.辅助功能基于两件事:

  1. 两个模块之间的读取边缘
  2. 访问的模块导出访问的类型

你没有写任何关于2.但如果module library { exports org.reflection.lib; },那么你可以自由地使用反射.原因是当您开始使用反射API时会自动添加读取边缘.

类型不可访问

现在它变得更有趣了.如果模块未导出org.reflection.lib或未ReflectiveClass公开,则上述方法不起作用.在这种情况下,您有很多选择可供选择:

  • 将类型设为public并导出包(可能只对访问模块)
  • 打开包(可能只对访问模块)或模块
  • 添加命令行选项以实现上述任何一项

要了解它们的比较,请查看有关Java 9中的反射与封装的文章.

  • 完毕。我之前没有在您的问题中看到“ClassNotFoundException”。直接跳到回答反思部分。(哎呀。) (2认同)