这个34:00 的演讲描述了StructuredArray
Java 的 s 设计。一切都很清楚,除了事情:
它不应该是可构造的,即实例可能只能通过一些静态工厂方法(如newInstance )获得。同时,它们应该是可子类化的,这意味着必须有一个公共的构造函数,并且在运行时保证不可构造性。这听起来很hacky,所以我想知道为什么?
我知道工厂的一般优势,特别是静态工厂方法的优势。但是我们在这里得到了什么,所以它使黑客可以接受?
这个34:00 的演讲描述了StructuredArray
Java 的 s 设计。一切都很清楚,除了事情:
它不应该是可构造的,即实例可能只能通过一些静态工厂方法(如newInstance )获得。同时,它们应该是可子类化的,这意味着必须有一个公共的构造函数,并且在运行时保证不可构造性。这听起来很hacky,所以我想知道为什么?
我知道工厂的一般优势,特别是静态工厂方法的优势。但是我们在这里得到了什么,所以它使黑客可以接受?
该类的重点StructuredArray
在于,有一天它可以被一个内部实现替换,该实现将整个数组(包括组件对象)分配为一个长内存块。 发生这种情况时,对象的大小将取决于元素的数量和元素类。
如果StructuredArray
有一个公共构造函数,那么你可以编写x = new StructuredArray<>(StructuredArray.class, MyElement.class, length)
. 这似乎没有任何问题,除了在bytecode中,这变成了new
分配对象的指令,然后是调用对象构造函数的单独指令。 invokespecial
你看到了问题——new
指令必须分配对象,但它不能,因为对象的大小取决于它没有的构造函数参数(元素类和长度)!直到稍后的构造函数调用才会传递这些。
有很多方法可以解决这样的问题,但它们都有点恶心。将构造封装在静态工厂方法中更有意义,因为这样您就无法编写 new StructuredArray...
,并且 JVM 不必使用任何“魔术”来计算要在new
指令中分配多少内存StructuredArray
,因为不可能有任何这样的指示*。
如果后来的 JVM 想要提供分配连续数组的静态工厂的内在实现,那没问题——它在工厂方法调用中获得了它需要的所有信息。
NB* - 是的,好的,从技术上讲你可以写new StructuredArray...
,但它对你没有用处。
语义浏览 API 文档,我的理解是,这主要是语义的问题。并提供 Fluent API。此外,如果您查看演示文稿的结论幻灯片,您应该注意到语义项目符号位于第一位(如果我们不计算源代码 url)。
如果我们选择普通数组。它们呈现出清晰的语义:
因此
我们有一个使用数组的统一模型。API 非常清晰。没有 10 种不同的方式来处理数组。我相信对于 Java 语言开发者来说,这种 api 的清洁度是极其重要的。强迫不可构造性,他们隐含地强迫我们以他们希望我们使用它的方式使用 API。
建造
由于 StructuredArray 本质上也是数组。提出一个构造函数将立即迫使我们使用 StructuredArray 的具体实现,这会自动产生问题,引入这个“究竟是什么是“数组?”的统一模型。
这就是为什么通过 Javadoc 我们可以看到 StructuredArray 的实际构造方式:
static <S extends StructuredArray<T>,T> S newInstance(java.lang.invoke.MethodHandles.Lookup lookup,
java.lang.Class<S> arrayClass,
java.lang.Class<T> elementClass,
java.util.Collection<T> sourceCollection)
这里可见的是 StructuredArray 正在强制执行几件事:
我相信有一个非常强大的语义符号,而且作者也给了我们一个很好的提示,告诉我们编码应该如何发生。
结构化数组的另一个有趣特性是能够传递构造函数。我们再次谈论的是接口和 API 与实际实现的强解耦。
阵列模型
通过检查StructuredArrayModel http://objectlayout.github.io/ObjectLayout/JavaDoc/index.html?org/ObjectLayout/StructuredArray.html,我的话得到了进一步证实
StructuredArrayModel(java.lang.Class<S> arrayClass, java.lang.Class<T> elementClass, long length)
从构造函数中可以看到三件事: - 数组类 - 元素的类型 - 长度
进一步观察结构化数组支持的结构:
An array of structs: struct foo[]; A struct with a struct inside: struct foo { int a; bar b; int c; }; A struct with an array at the end: struct foo { int len; char[] payload; };
StructuredArrayModel完全支持它 与StructuredArray 相比,我们能够轻松地实例化模型的具体实现。
StructuredArray 向我们展示了传递伪构造函数的能力http://objectlayout.github.io/ObjectLayout/JavaDoc/org/ObjectLayout/CtorAndArgs.html
newInstance(CtorAndArgs<S> arrayCtorAndArgs, java.lang.Class<T> elementClass, long length)