如何在Java模块中实现模块私有方法

如何在Java模块中实现模块私有方法,java,java-platform-module-system,Java,Java Platform Module System,我想创建一个Java IPC服务器模块(带有Jigsaw),它有两个包: com.example.ipc.backend com.example.ipc.backend.api 在mymodule info.java中,我有以下导出: module ipclib { exports com.example.ipc.backend.api; } 我可以在javafxgui模块中导入此模块,但在api模块中创建类时遇到问题 我在这个类中有一个接口,GUI模块中的某个类应该实现该接口,以

我想创建一个Java IPC服务器模块(带有Jigsaw),它有两个包:

  • com.example.ipc.backend
  • com.example.ipc.backend.api
在my
module info.java
中,我有以下导出:

module ipclib {
    exports com.example.ipc.backend.api;
}
我可以在javafxgui模块中导入此模块,但在
api
模块中创建类时遇到问题

我在这个类中有一个接口,GUI模块中的某个类应该实现该接口,以注册IPC模块中的更改(例如,当客户端连接到IPC服务器时):

然后,实现此接口的类应接收一个
客户端
,其中包含有关所连接客户端的信息。这个
Client
类在内部还保存了对线程的引用,该线程将套接字保存到客户端

public class Client {
    private IpcConnection connection; //IpcConnection is from com.example.ipc.backend

    public Client(IpcConnection connection) {
        this.connection = connection;
    }
}
现在我的问题是,每当创建新连接时,我都想在未导出的
后端
模块中创建
客户端
的实例。如何使构造函数仅在模块内可访问,而不公开

如果我将构造函数公开,IntelliJ会提供使用构造函数在GUI模块中创建新的客户端对象,但无权访问IpcConnection类。它提供了导出
后端
模块的快速修复,但这不是我在导出api时想要的

因此,我想知道这是否仍然是“允许的”,因为Java编译器编译它时没有任何警告和问题,而这只是IntelliJ的问题。还是不应该这样做

但是,如果不允许这样做,我想知道为什么模块系统实际上只允许导出一些包,因为导出包和未导出包之间总是有一个边界(除非未导出类是从导出类内部调用的,而不是相反)

最小项目 模块“后端” 模块“gui”
我认为,这在java中是不可能的。不能声明“在命名空间A及其所有子命名空间中可见”的接口

与.net相比,Java并不真正了解“内部”原则。 如果在接口或类定义中省略了单词
public
,则该元素仅在其当前包中可见

但这不是递归的,因为它是在.net中(在.net中,您创建了一个只在当前项目中可见的
internal
对象,无论是哪个子文件夹或名称空间)


在Java中,对象仅在其当前包中可见(即,同一名称空间)。子名称空间不包括在内。父命名空间也不是。

如果我理解正确,您有子包
A
B
,只有
A
是公开的
A
有一个类
C
,该类的构造函数应该从
B
调用,但不能公开


我认为最好的选择是让class
C
Client
)实现一个公共接口。因此接口类可以在公共包中,而实际实现可以在非公共包中。

您的问题有点难以理解。例如,在我认为您实际上是指“导出包”的地方,您一直使用术语“导出模块”。我也不完全确定您有哪些模块,哪些包在哪个模块中,或者每个类属于哪个包。你能不能请你的问题,让它更清楚你的确切设置是什么,以及你到底要完成什么?换句话说,a.谢谢,我添加了一个最小的示例。我对“我在这个类中有一个接口”有点困惑,我以为您有一个嵌套接口。您可以将
客户端
设为接口,然后将实现保存在非导出包中。啊,当然可以。太明显了。谢谢
public class Client {
    private IpcConnection connection; //IpcConnection is from com.example.ipc.backend

    public Client(IpcConnection connection) {
        this.connection = connection;
    }
}
// backend/src/main/java/module-info.java
module ipclib {
    exports com.example.ipc.backend.api;
}
// backend/src/main/java/com/example/ipc/backend/IpcConnection.java
package com.example.ipc.backend;

public class IpcConnection {
}
// backend/src/main/java/com/example/ipc/backend/api/Client.java
package com.example.ipc.backend.api;

import com.example.ipc.backend.IpcConnection;

public class Client {
    private IpcConnection connection;
    public Client(IpcConnection connection) {
        this.connection = connection;
    }
    public String hello() {
        return "Hello";
    }
}
// backend/src/main/java/com/example/ipc/backend/api/IpcCallback.java
package com.example.ipc.backend.api;

public interface IpcCallback {
    void clientConnected(Client client);
}
// gui/src/main/java/module-info.java
module gui {
    requires ipclib;
}
// gui/src/main/java/com/example/ipc/gui/App.java
package com.example.ipc.gui;

import com.example.ipc.backend.api.Client;
import com.example.ipc.backend.api.IpcCallback;

public class App implements IpcCallback {
    public static void main(String[] args) {

    }
    @Override
    public void clientConnected(Client client) {
        System.out.println(client.hello());
    }
}