未将Kotlin类标识为Flink有效的POJO的类

时间:2019-01-18 19:36:49

标签: kotlin apache-flink

我在Kotlin中编写Flink应用程序,并且数据类(以及其他Kotlin类)未标识为有效的POJO类型。 Flink文档指出,如果满足以下条件,则将数据类型识别为POJO类型(并允许“按名称”字段引用): 该课程是公开的和独立的 该类具有公共的无参数构造函数 类中的所有非静态,非瞬态字段都是公共的(非最终的)或具有遵循Java Bean命名约定的公共getter和setter方法。 在实现Kotlin数据类时,我收到以下内容,该类应满足上述条件才能被识别为POJO: [main]信息org.apache.flink.api.java.typeutils.TypeExtractor- 类类不能用作POJO类型,因为不是全部 字段是有效的POJO字段,并且必须作为GenericType处理。 请阅读Flink文档中的“数据类型和序列化” 有关对性能的影响的详细信息。 进一步调查后,我查看了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数据类,以试图缩小问题的范围。 数据类SomeDataClass(     val主题:String =“”,     val讯息:字串=“” ) 虽然Kotlin类字段默认情况下具有公共可见性,但Modifier.isPublic会将字段识别为私有字段。此外,Modifier.isFinal会将字段识别为final。 val clazz = SomeDataClass :: class.java val字段= 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)) } > 字段:私有最终java.lang.String SomeDataClass.topic 类java.lang.String 上市?假 最后?真正 短暂的?假 静态的?假 但是,将为这些字段创建public getter和setter方法,因此该对象仍应符合POJO标准。 println(clazz.declaredMethods.toList()) > [公共布尔SomeDataClass.equals(java.lang.Object), 公共java.lang.String SomeDataClass.toString(), 公共int SomeDataClass.hashCode(), **公共最终java.lang.String SomeDataClass.getMessage(),** 公共最终SomeDataClass SomeDataClass.copy(java.lang.String,java.lang.String), **公共最终java.lang.String SomeDataClass.getTopic(),** 公共最终java.lang.String SomeDataClass.component1(), 公共最终java.lang.String SomeDataClass.component2(), 公共静态SomeDataClass SomeDataClass.copy $ default(SomeDataClass,java.lang.String,java.lang.String,int,java.lang.Object)] 但是,getter和setter方法是最终的方法,这使我相信这是问题所在。 我对JVM开发比较陌生,因此将不胜感激。我已经查看了Flink Jira,Stack Overflow和Flink邮件列表,但未发现报告的类似问题。

1 个答案:

答案 0 :(得分:1)

我看到至少有两个POJO规则违反了提供的数据类。

1)该类具有公共的无参数构造函数

默认情况下,Kotlin不会为具有默认参数值(https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#overloads-generation)的函数生成重载

因此,已编译的类将只有一个带有两参数构造函数的构造函数,并且不会创建无参数构造函数。要强制Kotlin编译器生成多个重载,应使用@JvmOverloads批注。在您的情况下,它将用于构造函数,因此我们还需要添加constructor关键字:

data class SomeDataClass @JvmOverloads constructor

2)类中的所有非静态,非瞬态字段都是公共的(并且不是最终的),或者具有遵循Java bean命名约定的公共getter和setter方法。

由于您使用的是val关键字,因此生成的字段将为final,并且不会为它们生成设置器。因此,您可以将val更改为var,并且字段将不再是final,并且还将生成正确的getter和setter。 (或者,您可以使用其他注释来防止生成getter和setter并公开https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#instance-fields的字段)

因此最终代码应如下所示:

data class SomeDataClass @JvmOverloads constructor(
    var topic: String = "",
    var message: String = ""
)