链接应用返回类型似乎在编译时确定

时间:2017-12-10 19:50:30

标签: java apache-beam

有人可以向我解释以下代码行:

import org.apache.beam.sdk.Pipeline;
[..]
Pipeline p = Pipeline.create(options);
p.apply(TextIO.read().from("gs://apache-beam-samples/shakespeare/*"))
.apply("ExtractWords", ParDo.of(new DoFn<String, String>() {/* etc */}

我没有得到的是为什么这会编译。 Pipeline中的Apply方法返回T扩展POutput。 接口POutput没有任何apply方法。

在这种情况下,恰好是TextIO.read()。from(...)将PCollection作为POutput返回,并且THAT有一个apply方法。

但就管道合同而言,我们知道只会返回一个POutput。 那么编译器如何检查传递给第一个apply的参数的类型?从我编写Java时的记忆开始,只有在运行时才能看到它。

1 个答案:

答案 0 :(得分:0)

签名是:

public <OutputT extends POutput> OutputT apply(
    String name, PTransform<? super PBegin, OutputT> root) {
  ...
}

这意味着,对于任何可能延伸OutputT的{​​{1}}类型,此方法适用于POutput并返回(String, PTransform<? super PBegin, OutputT>)

OutputT返回TextIO.read(),其中TextIO.Read;它匹配PTransform<PBegin, PCollection<String>>

  • 类型PTransform<? super PBegin, OutputT>通常是PBegin
  • 的超类型
  • 类型PBegin扩展PCollection<String>

因此,POutput方法适用,替换为.apply()。在将OutputT = PCollection<String>的实际值替换为OutputT的签名后,返回值为.apply()

您所说的内容(PCollection<String>OutputT替换)在类型删除期间发生 - POutput的类型删除签名为{{1 }};这就是Pipeline.apply()编译的字节码中的签名,就JVM实际执行时而言而言。但是,在类型检查之后发生类型擦除,而不是之前 - 否则几乎所有使用泛型的Java程序都将无法编译。

这与调用POutput apply(String, PTransform)时发生的情况完全相同 - 它返回Pipeline而不是Arrays.asList(1, 2, 3)List<Integer>,即使类型删除的签名是List<Object>