You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by ja...@apache.org on 2019/05/05 11:38:55 UTC

[flink] branch master updated: [FLINK-12314][docs-zh] Translate the "Type Serialization" page into Chinese

This is an automated email from the ASF dual-hosted git repository.

jark pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/master by this push:
     new c375ce8  [FLINK-12314][docs-zh] Translate the "Type Serialization" page into Chinese
c375ce8 is described below

commit c375ce8940958efd0f571e387ba03bb892a9c460
Author: yangfei5 <ya...@xiaomi.com>
AuthorDate: Fri Apr 26 17:23:24 2019 +0800

    [FLINK-12314][docs-zh] Translate the "Type Serialization" page into Chinese
    
    This closes #8276
---
 docs/dev/types_serialization.zh.md | 285 +++++++++++++++++--------------------
 1 file changed, 128 insertions(+), 157 deletions(-)

diff --git a/docs/dev/types_serialization.zh.md b/docs/dev/types_serialization.zh.md
index acddcef..9fef921 100644
--- a/docs/dev/types_serialization.zh.md
+++ b/docs/dev/types_serialization.zh.md
@@ -1,5 +1,5 @@
 ---
-title: "Data Types & Serialization"
+title: "数据类型以及序列化"
 nav-id: types
 nav-parent_id: dev
 nav-show_overview: true
@@ -24,128 +24,115 @@ specific language governing permissions and limitations
 under the License.
 -->
 
-Apache Flink handles data types and serialization in a unique way, containing its own type descriptors,
-generic type extraction, and type serialization framework. This document describes the concepts and the rationale behind them.
+Apache Flink 以其独特的方式来处理数据类型以及序列化,这种方式包括它自身的类型描述符、泛型类型提取以及类型序列化框架。
+本文档描述了它们背后的概念和基本原理。
 
 * This will be replaced by the TOC
 {:toc}
 
 
-## Type handling in Flink
+## Flink 中的类型处理
 
-Flink tries to infer a lot of information about the data types that are exchanged and stored during the distributed computation.
-Think about it like a database that infers the schema of tables. In most cases, Flink infers all necessary information seamlessly
-by itself. Having the type information allows Flink to do some cool things:
+Flink 会尽力推断有关数据类型的大量信息,这些数据会在分布式计算期间被网络交换或存储。
+可以把它想象成一个推断表结构的数据库。在大多数情况下,Flink 可以依赖自身透明的推断出所有需要的类型信息。
+掌握这些类型信息可以帮助 Flink 实现很多意想不到的特性:
 
-* Using POJOs types and grouping / joining / aggregating them by referring to field names (like `dataSet.keyBy("username")`).
-  The type information allows Flink to check (for typos and type compatibility) early rather than failing later at runtime.
+* 对于使用 POJOs 类型的数据,可以通过指定字段名(比如 `dataSet.keyBy("username")` )进行 grouping 、joining、aggregating 操作。
+  类型信息可以帮助 Flink 在运行前做一些拼写错误以及类型兼容方面的检查,而不是等到运行时才暴露这些问题。
 
-* The more Flink knows about data types, the better the serialization and data layout schemes are.
-  That is quite important for the memory usage paradigm in Flink (work on serialized data inside/outside the heap where ever possible
-  and make serialization very cheap).
+* Flink 对数据类型了解的越多,序列化和数据布局方案就越好。
+  这对 Flink 中的内存使用范式尤为重要(可以尽可能处理堆上或者堆外的序列化数据并且使序列化操作很廉价)。
 
-* Finally, it also spares users in the majority of cases from worrying about serialization frameworks and having to register types.
+* 最后,它还使用户在大多数情况下免于担心序列化框架以及类型注册。
 
-In general, the information about data types is needed during the *pre-flight phase* - that is, when the program's calls on `DataStream`
-and `DataSet` are made, and before any call to `execute()`, `print()`, `count()`, or `collect()`.
+通常在应用*运行之前的阶段 (pre-flight phase)*,需要数据的类型信息 - 也就是在程序对 `DataStream` 或者
+`DataSet` 的操作调用之后,在 `execute()`、`print()`、`count()`、`collect()` 调用之前。
 
 
-## Most Frequent Issues
+## 最常见问题
 
-The most frequent issues where users need to interact with Flink's data type handling are:
+用户需要与 Flink 数据类型处理进行交互的最常见问题是:
 
-* **Registering subtypes:** If the function signatures describe only the supertypes, but they actually use subtypes of those during execution,
-  it may increase performance a lot to make Flink aware of these subtypes.
-  For that, call `.registerType(clazz)` on the `StreamExecutionEnvironment` or `ExecutionEnvironment` for each subtype.
+* **注册子类型** 如果函数签名只包含超类型,但它们实际上在执行期间使用那些类型的子类型,则使 Flink 感知这些子类型可能会大大提高性能。
+  可以为每一个子类型调用 `StreamExecutionEnvironment` 或者 `ExecutionEnvironment` 的 `.registerType(clazz)` 方法。
 
-* **Registering custom serializers:** Flink falls back to [Kryo](https://github.com/EsotericSoftware/kryo) for the types that it does not handle transparently
-  by itself. Not all types are seamlessly handled by Kryo (and thus by Flink). For example, many Google Guava collection types do not work well
-  by default. The solution is to register additional serializers for the types that cause problems.
-  Call `.getConfig().addDefaultKryoSerializer(clazz, serializer)` on the `StreamExecutionEnvironment` or `ExecutionEnvironment`.
-  Additional Kryo serializers are available in many libraries. See [Custom Serializers]({{ site.baseurl }}/dev/custom_serializers.html) for more details on working with custom serializers.
+* **注册自定义序列化器:** 当 Flink 无法通过自身处理类型时会回退到 [Kryo](https://github.com/EsotericSoftware/kryo) 进行处理。
+  并非所有的类型都可以被 Kryo (或者 Flink ) 处理。例如谷歌的 Guava 集合类型默认情况下是没办法很好处理的。
+  解决方案是为这些引起问题的类型注册额外的序列化器。调用 `StreamExecutionEnvironment` 或者 `ExecutionEnvironment` 
+  的 `.getConfig().addDefaultKryoSerializer(clazz, serializer)` 方法注册 Kryo 序列化器。存在很多的额外 Kryo 序列化器类库
+  具体细节可以参看 [自定义序列化器]({{ site.baseurl }}/zh/dev/custom_serializers.html) 以了解更多的自定义序列化器。
 
-* **Adding Type Hints:** Sometimes, when Flink cannot infer the generic types despite all tricks, a user must pass a *type hint*. That is generally
-  only necessary in the Java API. The [Type Hints Section](#type-hints-in-the-java-api) describes that in more detail.
+* **添加类型提示** 有时, Flink 用尽一切手段也无法推断出泛型类型,用户需要提供*类型提示*。通常只在 Java API 中需要。
+  [类型提示部分](#java-api-中的类型提示) 描述了更多的细节。
 
-* **Manually creating a `TypeInformation`:** This may be necessary for some API calls where it is not possible for Flink to infer
-  the data types due to Java's generic type erasure. See [Creating a TypeInformation or TypeSerializer](#creating-a-typeinformation-or-typeserializer)
-  for details.
+* **手动创建 `TypeInformation`:** 这可能是某些 API 调用所必需的,因为 Java 的泛型类型擦除会导致 Flink 无法推断出数据类型。
+  参考 [创建 TypeInformation 或者 TypeSerializer](#创建-typeinformation-或者-typeserializer)
 
+## Flink 的 TypeInformation 类
 
-## Flink's TypeInformation class
+类 {% gh_link /flink-core/src/main/java/org/apache/flink/api/common/typeinfo/TypeInformation.java "TypeInformation" %}
+是所有类型描述符的基类。该类表示类型的基本属性,并且可以生成序列化器,在一些特殊情况下可以生成类型的比较器。
+(*请注意,Flink 中的比较器不仅仅是定义顺序 - 它们是处理键的基础工具*)
 
-The class {% gh_link /flink-core/src/main/java/org/apache/flink/api/common/typeinfo/TypeInformation.java "TypeInformation" %}
-is the base class for all type descriptors. It reveals some basic properties of the type and can generate serializers
-and, in specializations, comparators for the types.
-(*Note that comparators in Flink do much more than defining an order - they are basically the utility to handle keys*)
+Flink 内部对类型做了如下区分:
 
-Internally, Flink makes the following distinctions between types:
+* 基础类型:所有的 Java 主类型(primitive)以及他们的包装类,再加上 `void`、`String`、`Date`、`BigDecimal` 以及 `BigInteger`。
 
-* Basic types: All Java primitives and their boxed form, plus `void`, `String`, `Date`, `BigDecimal`, and `BigInteger`.
+* 主类型数组(primitive array)以及对象数组
 
-* Primitive arrays and Object arrays
+* 复合类型
 
-* Composite types
+  * Flink 中的 Java 元组 (Tuples) (元组是 Flink Java API 的一部分):最多支持25个字段,null 是不支持的。 
 
-  * Flink Java Tuples (part of the Flink Java API): max 25 fields, null fields not supported
+  * Scala 中的 *case classes* (包括 Scala 元组):null 是不支持的。
 
-  * Scala *case classes* (including Scala tuples): null fields not supported
+  * Row:具有任意数量字段的元组并且支持 null 字段。。
 
-  * Row: tuples with arbitrary number of fields and support for null fields
+  * POJOs: 遵循某种类似 bean 模式的类。
 
-  * POJOs: classes that follow a certain bean-like pattern
+* 辅助类型 (Option、Either、Lists、Maps 等)
 
-* Auxiliary types (Option, Either, Lists, Maps, ...)
+* 泛型类型:这些不是由 Flink 本身序列化的,而是由 Kryo 序列化的。
 
-* Generic types: These will not be serialized by Flink itself, but by Kryo.
+POJOs 是特别有趣的,因为他们支持复杂类型的创建以及在键的定义中直接使用字段名:
+`dataSet.join(another).where("name").equalTo("personName")`
+它们对运行时也是透明的,并且可以由 Flink 非常高效地处理。
 
-POJOs are of particular interest, because they support the creation of complex types and the use of field
-names in the definition of keys: `dataSet.join(another).where("name").equalTo("personName")`.
-They are also transparent to the runtime and can be handled very efficiently by Flink.
+#### POJO 类型的规则
 
+如果满足以下条件,Flink 会将数据类型识别为 POJO 类型(并允许“按名称”引用字段):
 
-#### Rules for POJO types
+* 该类是公有的 (public) 和独立的(没有非静态内部类)
+* 该类拥有公有的无参构造器
+* 类(以及所有超类)中的所有非静态、非 transient 字段都是公有的(非 final 的),
+  或者具有遵循 Java bean 对于 getter 和 setter 命名规则的公有 getter 和 setter 方法。
 
-Flink recognizes a data type as a POJO type (and allows "by-name" field referencing) if the following
-conditions are fulfilled:
+请注意,当用户自定义的数据类型无法识别为 POJO 类型时,必须将其作为泛型类型处理并使用 Kryo 进行序列化。
 
-* The class is public and standalone (no non-static inner class)
-* The class has a public no-argument constructor
-* All non-static, non-transient fields in the class (and all superclasses) are either public (and non-final)
-  or have a public getter- and a setter- method that follows the Java beans
-  naming conventions for getters and setters.
+#### 创建 TypeInformation 或者 TypeSerializer
 
-Note that when a user-defined data type can't be recognized as a POJO type, it must be processed as GenericType and
-serialized with Kryo.
-
-
-#### Creating a TypeInformation or TypeSerializer
-
-To create a TypeInformation object for a type, use the language specific way:
+要为类型创建 TypeInformation 对象,需要使用特定于语言的方法:
 
 <div class="codetabs" markdown="1">
 <div data-lang="java" markdown="1">
-Because Java generally erases generic type information, you need to pass the type to the TypeInformation
-construction:
+因为 Java 会擦除泛型类型信息,所以需要将类型传入 TypeInformation 构造函数:
 
-For non-generic types, you can pass the Class:
+对于非泛型类型,可以传入类型的 Class 对象:
 {% highlight java %}
 TypeInformation<String> info = TypeInformation.of(String.class);
 {% endhighlight %}
 
-For generic types, you need to "capture" the generic type information via the `TypeHint`:
+对于泛型类型,你需要通过 `TypeHint` 来“捕获”泛型类型信息:
 {% highlight java %}
 TypeInformation<Tuple2<String, Double>> info = TypeInformation.of(new TypeHint<Tuple2<String, Double>>(){});
 {% endhighlight %}
-Internally, this creates an anonymous subclass of the TypeHint that captures the generic information to preserve it
-until runtime.
+在内部,这会创建 TypeHint 的匿名子类,捕获泛型信息并会将其保留到运行时。
 </div>
 
 <div data-lang="scala" markdown="1">
-In Scala, Flink uses *macros* that runs at compile time and captures all generic type information while it is
-still available.
+在 Scala 中,Flink 使用在编译时运行的*宏*捕获所有泛型类型信息。
 {% highlight scala %}
-// important: this import is needed to access the 'createTypeInformation' macro function
+// 注意:这个导入是为了访问 'createTypeInformation' 的宏函数
 import org.apache.flink.streaming.api.scala._
 
 val stringInfo: TypeInformation[String] = createTypeInformation[String]
@@ -153,51 +140,48 @@ val stringInfo: TypeInformation[String] = createTypeInformation[String]
 val tupleInfo: TypeInformation[(String, Double)] = createTypeInformation[(String, Double)]
 {% endhighlight %}
 
-You can still use the same method as in Java as a fallback.
+仍然可以使用与 Java 相同的方法作为后备。
 </div>
 </div>
 
-To create a `TypeSerializer`, simply call `typeInfo.createSerializer(config)` on the `TypeInformation` object.
+通过调用 `TypeInformation` 对象的 `typeInfo.createSerializer(config)` 方法可以简单的创建 `TypeSerializer` 对象。
 
-The `config` parameter is of type `ExecutionConfig` and holds the information about the program's registered
-custom serializers. Where ever possibly, try to pass the programs proper ExecutionConfig. You can usually
-obtain it from `DataStream` or `DataSet` via calling `getExecutionConfig()`. Inside functions (like `MapFunction`), you can
-get it by making the function a [Rich Function]() and calling `getRuntimeContext().getExecutionConfig()`.
+`config` 参数的类型是 `ExecutionConfig`,这个参数中持有程序注册的自定义序列化器信息。
+尽可能传入程序合适的 ExecutionConfig 。可以通过调用 `DataStream` 或者 `DataSet` 的 `getExecutionConfig()`
+函数获得 ExecutionConfig 对象。如果是在一个函数的内部 (比如 `MapFunction`),可以使这个函数首先成为
+{% gh_link /flink-core/src/main/java/org/apache/flink/api/common/functions/RichFunction.java "RichFunction" %}
+,然后通过调用 `getRuntimeContext().getExecutionConfig()` 获得 ExecutionConfig 对象。
 
 --------
 --------
 
-## Type Information in the Scala API
+## Scala API 中的类型信息
 
-Scala has very elaborate concepts for runtime type information though *type manifests* and *class tags*. In
-general, types and methods have access to the types of their generic parameters - thus, Scala programs do
-not suffer from type erasure as Java programs do.
+Scala 拥有精细的运行时类型信息概念 *type manifests* 以及 *class tags*。类型和方法通常可以访问他们泛型
+参数的类型 - 因此,Scala 程序不像 Java 程序那样需要面对类型擦除的问题。
 
-In addition, Scala allows to run custom code in the Scala Compiler through Scala Macros - that means that some Flink
-code gets executed whenever you compile a Scala program written against Flink's Scala API.
+此外,Scala 允许通过 Scala 宏在 Scala 编译器中运行自定义代码 - 这意味着无论何时编译使用 Flink Scala API 
+编写的 Scala 程序,都会执行一些 Flink 代码。
 
-We use the Macros to look at the parameter types and return types of all user functions during compilation - that
-is the point in time when certainly all type information is perfectly available. Within the macro, we create
-a *TypeInformation* for the function's return types (or parameter types) and make it part of the operation.
+我们在编译期间使用宏来查看所有用户自定义函数的参数类型和返回类型 - 这是所有类型信息都完全可用的时间点。
+在宏中,我们为函数的返回类型(或参数类型)创建了 *TypeInformation*,并使其成为操作的一部分。
 
 
-#### No Implicit Value for Evidence Parameter Error
+#### No Implicit Value for Evidence Parameter 错误
 
-In the case where TypeInformation could not be created, programs fail to compile with an error
-stating *"could not find implicit value for evidence parameter of type TypeInformation"*.
+当 TypeInformation 创建失败的时候,程序会抛出错误信息 *"could not find implicit value for evidence parameter of type TypeInformation"*
 
-A frequent reason if that the code that generates the TypeInformation has not been imported.
-Make sure to import the entire flink.api.scala package.
+产生这样错误最常见的原因是没有导入生成 TypeInformation 的代码。需要导入完整的 flink.api.scala  包。
 {% highlight scala %}
 import org.apache.flink.api.scala._
 {% endhighlight %}
 
-Another common cause are generic methods, which can be fixed as described in the following section.
+另一个常见原因是泛型方法,可以按照以下部分所述进行修复。
 
 
-#### Generic Methods
+#### 泛型方法
 
-Consider the following case below:
+考虑下面的代码:
 
 {% highlight scala %}
 def selectFirst[T](input: DataSet[(T, _)]) : DataSet[T] = {
@@ -209,16 +193,13 @@ val data : DataSet[(String, Long) = ...
 val result = selectFirst(data)
 {% endhighlight %}
 
-For such generic methods, the data types of the function parameters and return type may not be the same
-for every call and are not known at the site where the method is defined. The code above will result
-in an error that not enough implicit evidence is available.
+对于上面这样的泛型方法,函数的参数类型以及返回类型可能每一次调用都是不同的并且没有办法在方法定义的时候被感知到。
+上面的代码将导致没有足够的隐式转换可用错误。
 
-In such cases, the type information has to be generated at the invocation site and passed to the
-method. Scala offers *implicit parameters* for that.
+在这种情况下,类型信息必须在调用时间点生成并将其传递给方法。Scala 为此提供了*隐式转换*。
 
-The following code tells Scala to bring a type information for *T* into the function. The type
-information will then be generated at the sites where the method is invoked, rather than where the
-method is defined.
+下面的代码告诉 Scala 将 *T* 的类型信息带入函数中。类型信息会在方法被调用的时间生成,而不是
+方法定义的时候。
 
 {% highlight scala %}
 def selectFirst[T : TypeInformation](input: DataSet[(T, _)]) : DataSet[T] = {
@@ -231,11 +212,10 @@ def selectFirst[T : TypeInformation](input: DataSet[(T, _)]) : DataSet[T] = {
 --------
 
 
-## Type Information in the Java API
+## Java API 中的类型信息
 
-In the general case, Java erases generic type information. Flink tries to reconstruct as much type information
-as possible via reflection, using the few bits that Java preserves (mainly function signatures and subclass information).
-This logic also contains some simple type inference for cases where the return type of a function depends on its input type:
+Java 会擦除泛型类型信息。Flink 使用 Java 预留的少量位(主要是函数签名以及子类信息)通过反射尽可能多的重新构造类型信息。
+对于依赖输入类型来确定函数返回类型的情况,此逻辑还包含一些简单类型推断:
 
 {% highlight java %}
 public class AppendOne<T> implements MapFunction<T, Tuple2<T, Long>> {
@@ -246,14 +226,12 @@ public class AppendOne<T> implements MapFunction<T, Tuple2<T, Long>> {
 }
 {% endhighlight %}
 
-There are cases where Flink cannot reconstruct all generic type information. In that case, a user has to help out via *type hints*.
+在某些情况下,Flink 无法重建所有泛型类型信息。 在这种情况下,用户必须通过*类型提示*来解决问题。
 
+#### Java API 中的类型提示
 
-#### Type Hints in the Java API
-
-In cases where Flink cannot reconstruct the erased generic type information, the Java API
-offers so called *type hints*. The type hints tell the system the type of
-the data stream or data set produced by a function:
+在 Flink 无法重建被擦除的泛型类型信息的情况下,Java API 需要提供所谓的*类型提示*。
+类型提示告诉系统 DateStream 或者 DateSet 产生的类型:
 
 {% highlight java %}
 DataSet<SomeType> result = dataSet
@@ -261,83 +239,76 @@ DataSet<SomeType> result = dataSet
         .returns(SomeType.class);
 {% endhighlight %}
 
-The `returns` statement specifies the produced type, in this case via a class. The hints support
-type definition via
-
-* Classes, for non-parameterized types (no generics)
-* TypeHints in the form of `returns(new TypeHint<Tuple2<Integer, SomeType>>(){})`. The `TypeHint` class
-  can capture generic type information and preserve it for the runtime (via an anonymous subclass).
+在上面情况下 `returns` 表达通过 Class 类型指出产生的类型。通过下面方式支持类型提示:
 
+* 对于非参数化的类型(没有泛型)的 Class 类型
+* 以 `returns(new TypeHint<Tuple2<Integer, SomeType>>(){})` 方式进行类型提示。
+  `TypeHint` 类可以捕获泛型的类型信息并且保存到执行期间(通过匿名子类)。
 
-#### Type extraction for Java 8 lambdas
+#### Java 8 lambdas 的类型提取
 
-Type extraction for Java 8 lambdas works differently than for non-lambdas, because lambdas are not associated
-with an implementing class that extends the function interface.
+Java 8 lambdas 的类型提取与非-lambdas 不同,因为 lambdas 与扩展函数接口的实现类没有关联。
 
-Currently, Flink tries to figure out which method implements the lambda and uses Java's generic signatures to
-determine the parameter types and the return type. However, these signatures are not generated for lambdas
-by all compilers (as of writing this document only reliably by the Eclipse JDT compiler from 4.5 onwards).
+Flink 目前试图找出实现 lambda 的方法,并使用 Java 的泛型签名来确定参数类型和返回类型。 
+但是,并非所有编译器都为 lambda 生成这些签名(此文档写作时,只有 Eclipse JDT 编译器从4.5开始可靠支持)。
 
 
-#### Serialization of POJO types
+#### POJO 类型的序列化
 
-The PojoTypeInformation is creating serializers for all the fields inside the POJO. Standard types such as
-int, long, String etc. are handled by serializers we ship with Flink.
-For all other types, we fall back to Kryo.
+PojoTypeInformation 为 POJO 中的所有字段创建序列化器。Flink 标准类型如 int、long、String 等由 Flink 序列化器处理。
+对于所有其他类型,我们回退到 Kryo。
 
-If Kryo is not able to handle the type, you can ask the PojoTypeInfo to serialize the POJO using Avro.
-To do so, you have to call
+对于 Kryo 不能处理的类型,你可以要求 PojoTypeInfo 使用 Avro 对 POJO 进行序列化。
+需要通过下面的代码开启。
 
 {% highlight java %}
 final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
 env.getConfig().enableForceAvro();
 {% endhighlight %}
 
-Note that Flink is automatically serializing POJOs generated by Avro with the Avro serializer.
+请注意,Flink 会使用 Avro 序列化器自动序列化 Avro 生成的 POJO。
 
-If you want your **entire** POJO Type to be treated by the Kryo serializer, set
+通过下面设置可以让你的**整个** POJO 类型被 Kryo 序列化器处理。
 
 {% highlight java %}
 final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
 env.getConfig().enableForceKryo();
 {% endhighlight %}
 
-If Kryo is not able to serialize your POJO, you can add a custom serializer to Kryo, using
+如果 Kryo 不能序列化你的 POJO,可以通过下面的代码添加自定义的序列化器
 {% highlight java %}
 env.getConfig().addDefaultKryoSerializer(Class<?> type, Class<? extends Serializer<?>> serializerClass)
 {% endhighlight %}
 
-There are different variants of these methods available.
+这些方法有不同的变体可供选择。
 
 
-## Disabling Kryo Fallback
+## 禁止回退到 Kryo
 
-There are cases when programs may want to explicitly avoid using Kryo as a fallback for generic types. The most
-common one is wanting to ensure that all types are efficiently serialized either through Flink's own serializers,
-or via user-defined custom serializers.
+对于泛型信息,程序可能希望在一些情况下显示的避免使用 Kryo。最常见的场景是,用户想要确保所有的类型都可以通过 Flink 自身
+或者用户自定义的序列化器高效的进行序列化操作。
 
-The setting below will raise an exception whenever a data type is encountered that would go through Kryo:
+下面的设置将引起通过 Kryo 的数据类型抛出异常:
 {% highlight java %}
 env.getConfig().disableGenericTypes();
 {% endhighlight %}
 
 
-## Defining Type Information using a Factory
+## 使用工厂方法定义类型信息
 
-A type information factory allows for plugging-in user-defined type information into the Flink type system.
-You have to implement `org.apache.flink.api.common.typeinfo.TypeInfoFactory` to return your custom type information. 
-The factory is called during the type extraction phase if the corresponding type has been annotated 
-with the `@org.apache.flink.api.common.typeinfo.TypeInfo` annotation. 
+类型信息工厂允许将用户定义的类型信息插入 Flink 类型系统。
+你可以通过实现 `org.apache.flink.api.common.typeinfo.TypeInfoFactory` 来返回自定义的类型信息工厂。
+如果相应的类型已指定了 `@org.apache.flink.api.common.typeinfo.TypeInfo` 注解,则在类型提取阶段会调用 TypeInfo 注解指定的
+类型信息工厂。
 
-Type information factories can be used in both the Java and Scala API.
+类型信息工厂可以在 Java 和 Scala API 中使用。
 
-In a hierarchy of types the closest factory 
-will be chosen while traversing upwards, however, a built-in factory has highest precedence. A factory has 
-also higher precedence than Flink's built-in types, therefore you should know what you are doing.
+在类型的层次结构中,在向上遍历时将选择最近的工厂,但是内置工厂具有最高优先级。
+工厂的优先级也高于 Flink 的内置类型,因此你应该知道自己在做什么。
 
-The following example shows how to annotate a custom type `MyTuple` and supply custom type information for it using a factory in Java.
+以下示例说明如何使用 Java 中的工厂注释为自定义类型 `MyTuple` 提供自定义类型信息。
 
-The annotated custom type:
+带注解的自定义类型:
 {% highlight java %}
 @TypeInfo(MyTupleTypeInfoFactory.class)
 public class MyTuple<T0, T1> {
@@ -346,7 +317,7 @@ public class MyTuple<T0, T1> {
 }
 {% endhighlight %}
 
-The factory supplying custom type information:
+支持自定义类型信息的工厂:
 {% highlight java %}
 public class MyTupleTypeInfoFactory extends TypeInfoFactory<MyTuple> {
 
@@ -357,11 +328,11 @@ public class MyTupleTypeInfoFactory extends TypeInfoFactory<MyTuple> {
 }
 {% endhighlight %}
 
-The method `createTypeInfo(Type, Map<String, TypeInformation<?>>)` creates type information for the type the factory is targeted for. 
-The parameters provide additional information about the type itself as well as the type's generic type parameters if available.
+方法 `createTypeInfo(Type, Map<String, TypeInformation<?>>)` 为工厂所对应的类型创建类型信息。
+参数提供有关类型本身的额外信息以及类型的泛型类型参数。
 
-If your type contains generic parameters that might need to be derived from the input type of a Flink function, make sure to also 
-implement `org.apache.flink.api.common.typeinfo.TypeInformation#getGenericParameters` for a bidirectional mapping of generic 
-parameters to type information.
+如果你的类型包含可能需要从 Flink 函数的输入类型派生的泛型参数,
+请确保还实现了 `org.apache.flink.api.common.typeinfo.TypeInformation#getGenericParameters`,
+以便将泛型参数与类型信息进行双向映射。
 
 {% top %}