2

我几乎可以肯定有人问过这个问题,但我不确定要搜索什么。

无论如何,我很好奇是否可以创建一个扩展类ByteBuffer。我认为这是不可能的,因为ByteBuffer有包私有的构造函数:

// package-private
ByteBuffer(int mark, int pos, int lim, int cap, byte[] hb, int offset) {
    super(mark, pos, lim, cap);
    this.hb = hb;
    this.offset = offset;
}

// Creates a new buffer with the given mark, position, limit, and capacity
//
ByteBuffer(int mark, int pos, int lim, int cap) { // package-private
    this(mark, pos, lim, cap, null, 0);
}

但是,我发现如果您在与其父级共享名称的包中创建您的类,那么它可以完美编译。

package java.nio;

public class Test extends ByteBuffer {
    Test(int mark, int pos, int lim, int cap, byte[] hb, int offset) {
        super(mark, pos, lim, cap, hb, offset);
    }

    @Override
    public ByteBuffer slice() {
        return null;
    }

    ...
}   

它也可以在 Java 9 和 Java 10 中编译,但仅--patch-module在编译时使用:

javac --patch-module java.base=. java/nio/Test.java

我的问题是:这是如何(以及为什么)编译的?

4

1 回答 1

3

包(共享名称)是否在编译过程中合并?

不完全是。包名唯一标识一个包。每个名字只有一个。

但是包成员的 Java 源代码不必全部驻留在同一源代码树中或同时编译。Java 编译器将接受您的类对任何有效包名称的声明,并接受您的类在他们所说的包中。

另一方面,这并不意味着您可以使用您声明在任何给定 JVM中的 ajava.*或package 中的类。javax.*标准 JVM 将拒绝从 JVM 外部的任何源加载属于这些包的类。您可以构建这样的类,但不能使用它们。您可以通过一种称为“包装密封”的机制以几乎相同的方式保护自己的包装。

另一方面,使用未密封的包,您确实可以从多个不同的来源加载包成员。

于 2018-08-07T01:23:40.320 回答