Kotlin警告:在构造函数中访问非final属性。

4

我有以下代码,但是producer变量在构造函数中访问了非final属性,导致出现警告。

class KafkaService {

  val producer: KafkaProducer<String, String>

  init {
    val props = Properties()
    props[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = "127.0.0.1:9092"
    props[ProducerConfig.CLIENT_ID_CONFIG] = "DemoProducer"
    props[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java.name
    props[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java.name

    producer = KafkaProducer(props)
  }

  fun sendToKafka(topic: String, message: String) {
    val producerRecord: ProducerRecord<String?, String> = ProducerRecord(topic, null, message)
    producer.send(producerRecord)
  }
}

什么是最好的解决方法?

1
用这段代码?producer没有被打开,你也没有访问它,只是初始化。 - Alexey Romanov
2个回答

5
你应该将producer变量初始化为lazy:
class KafkaService {

  val producer: KafkaProducer<String, String> by lazy {
    val props = Properties()
    props[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = "127.0.0.1:9092"
    props[ProducerConfig.CLIENT_ID_CONFIG] = "DemoProducer"
    props[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java.name
    props[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java.name

    KafkaProducer(props)
  }

  fun sendToKafka(topic: String, message: String) {
    val producerRecord: ProducerRecord<String?, String> = ProducerRecord(topic, null, message)
    producer.send(producerRecord)
  }
}

这样,当您第一次访问变量时,它将被初始化,您不会重新分配最终变量。阅读此文以更好地理解。


能否修改代码,在应用程序启动时初始化KafkaProducer,而不是在我们第一次访问它时初始化? - ttt
你可以定义一个 initialize 方法,并在你的 Application 类的 onCreate 方法中调用它,但是,除非初始化很慢并且想要预加载它,否则与懒加载相比不会有任何区别。 - DAA

0

producer 应该被声明为 final 以消除此警告。可以使用 final 关键字或将其设置为私有,这将使其隐式成为 final

注意:在 Kotlin 中,finalopen 的相反,意思是“不能被覆盖”。请参见 Inheritance。对于习惯于 Java 的人来说,请注意,在 Java 中,final 有两个不同的含义:

  • “不能被覆盖”(就像在 Kotlin 中一样),
  • 但也“只分配一次”(Kotlin 使用 val 关键字)。

注意:在 Kotlin 中,默认情况下,属性是 final 的,因此 OP 没有分享的内容可能会打开 producer。也许是 all-open 编译器插件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接