有人可以向我解释以下代码行:
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时的记忆开始,只有在运行时才能看到它。
答案 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>
。