【发布时间】:2019-06-13 02:20:53
【问题描述】:
我正在用 Kotlin 编写 Flink 应用程序,并且数据类(以及其他 Kotlin 类)未被识别为有效的 POJO 类型。
Flink 文档指出,如果满足以下条件,则数据类型被识别为 POJO 类型(并允许“按名称”字段引用):
- 该类是公共的且独立的
- 该类有一个公共的无参数构造函数
- 类中的所有非静态、非瞬态字段要么是公共的(非最终的),要么具有遵循 Java bean 命名约定的公共 getter 和 setter 方法。
我在实现 Kotlin 数据类时收到以下信息,它应该满足上述条件才能被识别为 POJO:
[main] INFO org.apache.flink.api.java.typeutils.TypeExtractor -
Class class <Class> cannot be used as a POJO type because not all
fields are valid POJO fields, and must be processed as GenericType.
Please read the Flink documentation on "Data Types & Serialization"
for details of the effect on performance.
进一步调查,我查看了 Flink 的 TypeExtractor.isValidPojoField 方法@https://github.com/apache/flink/blob/master/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java
在一个单独的项目中,我使用 java.lang.reflect.Modifier 对一个简单的 Kotlin 数据类应用了字段检查,以试图缩小问题范围。
data class SomeDataClass(
val topic: String = "",
val message: String = ""
)
虽然 Kotlin 类字段默认具有公共可见性,但 Modifier.isPublic 将这些字段识别为私有。此外,Modifier.isFinal 将字段识别为 final。
val clazz = SomeDataClass::class.java
val fields = clazz.declaredFields
fields.forEach { it ->
println("field: $it")
println(it.genericType)
println("public? " + Modifier.isPublic(it.modifiers))
println("final? " + Modifier.isFinal(it.modifiers))
println("transient? " + Modifier.isTransient(it.modifiers))
println("static? " + Modifier.isStatic(it.modifiers))
}
>
field: private final java.lang.String SomeDataClass.topic
class java.lang.String
public? false
final? true
transient? false
static? false
但是,为这些字段创建了公共 getter 和 setter 方法,因此该对象仍应符合 POJO 标准。
println(clazz.declaredMethods.toList())
>
[public boolean SomeDataClass.equals(java.lang.Object),
public java.lang.String SomeDataClass.toString(),
public int SomeDataClass.hashCode(),
**public final java.lang.String SomeDataClass.getMessage(),**
public final SomeDataClass SomeDataClass.copy(java.lang.String,java.lang.String),
**public final java.lang.String SomeDataClass.getTopic(),**
public final java.lang.String SomeDataClass.component1(),
public final java.lang.String SomeDataClass.component2(),
public static SomeDataClass SomeDataClass.copy$default(SomeDataClass,java.lang.String,java.lang.String,int,java.lang.Object)]
然而,getter 和 setter 方法是最终的,这让我相信这是问题所在。
我对 JVM 开发比较陌生,因此我们将不胜感激。我查看了 Flink Jira、Stack Overflow 和 Flink 邮件列表,没有发现类似的问题报告。
【问题讨论】:
-
如果问题只是数据类的最终修饰符,您可以使用“全开放”kotlin 插件将它们从编译代码中删除。
标签: kotlin apache-flink