为什么StructuredArray需要不可构造?

时间:2016-07-21 19:54:52

标签: java arrays struct collections java-9

34:00的

This talk描述了Java StructuredArray的设计。一切都很清楚,除了东西:

它不应该是可构造的,即实例可能只能通过某些静态工厂方法获得,如newInstance。同时,它们应该是子类,这意味着必须有一个公共构造函数,并且在运行时将确保不可构造性。这听起来非常h​​acky,所以我想知道为什么?

我了解工厂的一般优势和静态工厂方法。但是我们得到了什么,这样才能让黑客接受?

2 个答案:

答案 0 :(得分:3)

StructuredArray类的要点是,有一天它可以被一个内部实现替换,该实现将整个数组(包括组件对象)分配为一个长内存块。 当发生这种情况时,对象的大小将取决于元素的数量和元素类

如果StructuredArray有公共构造函数,那么您可以编写x = new StructuredArray<>(StructuredArray.class, MyElement.class, length)。这似乎没有任何问题,除了在字节码中,这变成了分配对象的new指令,然后是单独的 {{ 1}}调用对象构造函数的指令。

您看到问题 - invokespecial指令必须分配对象,但不能,因为对象的大小取决于构造函数参数(元素类和长度)它没有!直到稍后的构造函数调用之后才会传递它们。

有很多方法可以解决这类问题,但它们都有点粗糙。将构造封装在静态工厂方法中更有意义,因为那时你只是无法编写 new,并且JVM不必使用任何“魔法”来计算new StructuredArray... new指令中要分配的内存量,因为不能有任何此类指令*。

如果某个后来的JVM想要提供分配连续数组的静态工厂的内部实现,那么它就没问题了 - 它在工厂方法调用中获取了所需的所有信息。

NB * - 是的,好的,从技术上讲,你可以StructuredArray,但它不会为你提供有用的对象。

答案 1 :(得分:2)

语义通过API文档,我的理解是它主要是一个Semantics的问题。并提供Fluent API。此外,如果您转到演示文稿的结论幻灯片,您应该注意到Semantics项目符号首先出现(如果我们不计算源代码URL)。

如果我们选择正常的数组。它们提供了明确的语义:

  • 数组类型
  • 数组的长度
  • 元素类型

结果

我们有一个使用数组的统一模型。 API非常清晰。没有10种不同的方法来处理数组。我相信对于Java语言开发人员来说,api的这种清洁是非常重要的。强制不可构造性,它们隐含地迫使我们按照他们希望我们使用它的方式使用API​​。

<强>建筑

由于StructuredArray本质上也是数组。提出一个构造函数会立即迫使我们使用StructuredArray的Concrete实现,它会自动引入问题,引入这个统一的&#34;&#34;数组究竟是什么?&#34;

这就是为什么通过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强制执行以下操作:

  1. 强制所有客户端类使用&#34; StructuredArray&#34;而不是具体的实施。
  2. StructuredArray本质上是不可变的。
  3. 不变性意味着有严格的长度符号。
  4. 结构化数组具有元素源。曾经消费过的可能会被处理掉。
  5. 与常规数组类似,结构化数组具有TYPE元素的概念。
  6. 我相信有一个非常强大的语义符号,而且作者正在给我们一个很好的暗示如何编码应该发生。

    结构化数组的另一个有趣特性是能够传递构造函数。我们再次讨论了接口和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)