Scala 类 final def this() 声明没有公共无参数构造函数



尝试构建一个通用的 Scala 2.11 Jackson 序列化程序,该序列化程序使用 Jackson Smile 2.6.6 和 jackson-module-scala。无论出于何种原因,Java都找不到一个公共的无参数构造函数。尽管下面的类可以编译,但我在运行时从 Kafka 客户端收到以下错误:

Caused by: org.apache.kafka.common.KafkaException: Could not instantiate class ai.bernie.api.util.serialization.kafka.JacksonGenericSerializer Does it have a public no-argument constructor?
    at org.apache.kafka.common.utils.Utils.newInstance(Utils.java:318) ~[kafka-clients-0.10.0.0.jar:na]
    at org.apache.kafka.common.config.AbstractConfig.getConfiguredInstance(AbstractConfig.java:201) ~[kafka-clients-0.10.0.0.jar:na]
    at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:671) ~[kafka-clients-0.10.0.0.jar:na]
    ... 27 common frames omitted
Caused by: java.lang.InstantiationException: ai.bernie.api.util.serialization.kafka.JacksonGenericSerializer
    at java.lang.Class.newInstance(Class.java:427) ~[na:1.8.0_51]
    at org.apache.kafka.common.utils.Utils.newInstance(Utils.java:314) ~[kafka-clients-0.10.0.0.jar:na]
    ... 29 common frames omitted
Caused by: java.lang.NoSuchMethodException: ai.bernie.api.util.serialization.kafka.JacksonGenericSerializer.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_51]
    at java.lang.Class.newInstance(Class.java:412) ~[na:1.8.0_51]
    ... 30 common frames omitted

这是类,我该如何解决它?我已经尝试了使用 final def 并将私有 var 移动到类中的各种组合,尽管我可能做错了,但也尝试使用无参数apply方法创建一个伴随对象。

class JacksonGenericSerializer[T: Manifest] private (
  private var mapper: ObjectMapper with ScalaObjectMapper = null
) extends Closeable with AutoCloseable with Serializer[T] with Deserializer[T] {
  final def this() = this(new ObjectMapper(new SmileFactory) with ScalaObjectMapper)
  override def configure(map: java.util.Map[String, _], b: Boolean) {
    if (mapper == null) {
      mapper = new ObjectMapper(new SmileFactory) with ScalaObjectMapper
      mapper.registerModule(DefaultScalaModule)
    }
  }
  override def serialize(s: String, record: T): Array[Byte] = {
    try {
      mapper.writeValueAsBytes(record)
    }
    catch {
      case e: JsonProcessingException => {
        throw new IllegalArgumentException(e)
      }
    }
  }
  override def deserialize(s: String, bytes: Array[Byte]): T = {
    try {
      mapper.readValue[T](bytes)
    }
    catch {
      case e: IOException => {
        throw new IllegalArgumentException(e)
      }
    }
  }
  override def close {
    mapper = null
  }
}

编辑

我还应该提到我正在使用 Google Guice,尽管我怀疑它会影响这一点,因为序列化类本身没有被注入,只有使用它的 Kafka 消费者/生产者父类。

因为JacksonGenericSerializer类型参数具有上下文绑定(即 [T: Manifest] )辅助的"无参数"构造函数实际上接受一个参数:Manifest[T]

您可以使用javap确认这一点:

$ javap JacksonGenericSerializer.class
Compiled from "JacksonGenericSerializer.scala"
public class JacksonGenericSerializer<T> implements java.io.Closeable, java.lang.AutoCloseable, org.apache.kafka.common.serialization.Serializer<T>, org.apache.kafka.common.serialization.Deserializer<T> {
  public void configure(java.util.Map<java.lang.String, ?>, boolean);
  public byte[] serialize(java.lang.String, T);
  public T deserialize(java.lang.String, byte[]);
  public void close();
  public JacksonGenericSerializer(scala.reflect.Manifest<T>);
}

这个问题涉及一个类似的问题:如何仅使用零参数构造函数通过 Java 反射创建上下文绑定的 Scala 类的新实例?

最新更新