Kotlin 覆盖歧义
Kotlin override ambiguity
我必须为我的 Quarkus 应用程序创建自定义日志记录提供程序,以将日志条目转换为 Google 云 JSON 格式。
为此,提供者 class(用 Kotlin 编写)必须扩展名为 ExtFormatter
的抽象 class(来自第 3 方库,用 Java 编写),它有这两种方法:
package org.jboss.logmanager;
[...]
public abstract class ExtFormatter extends Formatter {
public final String format(final LogRecord record) {
return format(ExtLogRecord.wrap(record));
}
[...]
}
public abstract String format(ExtLogRecord record);
ExtLogRecord
是 LogRecord
的子 class,因此方法签名非常相似。
我的日志提供程序实现了这样的抽象方法:
import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtFormatter
import org.jboss.logmanager.ExtLogRecord
[...]
class JsonLoggingProvider : JsonProvider, ExtFormatter() {
override fun format(extLogRecord: ExtLogRecord?) = null
}
当我 运行 应用程序时(不是在编译时),我得到这个错误:
java.lang.VerifyError: class com.mycompany.logging.JsonLoggingProvider_Subclass overrides final method org.jboss.logmanager.ExtFormatter.format(Ljava/util/logging/LogRecord;)Ljava/lang/String;
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:437)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:397)
at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:368)
at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:394)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:426)
at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:442)
at io.quarkus.arc.impl.InstanceImpl.getBeanInstance(InstanceImpl.java:210)
at io.quarkus.arc.impl.InstanceImpl$InstanceIterator.next(InstanceImpl.java:246)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at io.quarkiverse.loggingjson.LoggingJsonRecorder.initializeJsonLogging(LoggingJsonRecorder.java:62)
at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy_0(LoggingJsonProcessor$setUpFormatter-614569086.zig:88)
at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy(LoggingJsonProcessor$setUpFormatter-614569086.zig:40)
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:666)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:98)
at java.base/java.lang.Thread.run(Thread.java:829)
由于某种原因,错误的方法(或两种方法?)似乎被覆盖了。
我怀疑它的发生是因为这些方法或多或少具有相同的签名。
有没有办法让 Kotlin 覆盖更精确以避免这个问题?
与我最初的假设相反,问题显然不是由 Kotlin 引起的,而是由 Quarkus 引起的。依赖注入似乎被非常相似的方法搞糊涂了。由于我无法更改任何方法名称或签名,因为它们来自第三方 Quarkiverse 库,因此我通过不再子类化 ExtFormatter
来解决这个问题,而是实例化它的一个已经存在的子类 JsonFormatter
:
import io.quarkiverse.loggingjson.JsonGenerator
import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtLogRecord
import org.jboss.logmanager.formatters.JsonFormatter
[...]
class JsonLoggingProvider : JsonProvider {
private val jsonFormatter = JsonFormatter()
private fun writeMessage(generator: JsonGenerator, event: ExtLogRecord) {
val message = jsonFormatter.formatMessage(event)
[...]
}
}
再次感谢broot帮助我!
我必须为我的 Quarkus 应用程序创建自定义日志记录提供程序,以将日志条目转换为 Google 云 JSON 格式。
为此,提供者 class(用 Kotlin 编写)必须扩展名为 ExtFormatter
的抽象 class(来自第 3 方库,用 Java 编写),它有这两种方法:
package org.jboss.logmanager;
[...]
public abstract class ExtFormatter extends Formatter {
public final String format(final LogRecord record) {
return format(ExtLogRecord.wrap(record));
}
[...]
}
public abstract String format(ExtLogRecord record);
ExtLogRecord
是 LogRecord
的子 class,因此方法签名非常相似。
我的日志提供程序实现了这样的抽象方法:
import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtFormatter
import org.jboss.logmanager.ExtLogRecord
[...]
class JsonLoggingProvider : JsonProvider, ExtFormatter() {
override fun format(extLogRecord: ExtLogRecord?) = null
}
当我 运行 应用程序时(不是在编译时),我得到这个错误:
java.lang.VerifyError: class com.mycompany.logging.JsonLoggingProvider_Subclass overrides final method org.jboss.logmanager.ExtFormatter.format(Ljava/util/logging/LogRecord;)Ljava/lang/String;
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:437)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:397)
at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:368)
at com.mycompany.logging.JsonLoggingProvider_Bean.create(JsonLoggingProvider_Bean.zig:394)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:426)
at com.mycompany.logging.JsonLoggingProvider_Bean.get(JsonLoggingProvider_Bean.zig:442)
at io.quarkus.arc.impl.InstanceImpl.getBeanInstance(InstanceImpl.java:210)
at io.quarkus.arc.impl.InstanceImpl$InstanceIterator.next(InstanceImpl.java:246)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at io.quarkiverse.loggingjson.LoggingJsonRecorder.initializeJsonLogging(LoggingJsonRecorder.java:62)
at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy_0(LoggingJsonProcessor$setUpFormatter-614569086.zig:88)
at io.quarkus.deployment.steps.LoggingJsonProcessor$setUpFormatter-614569086.deploy(LoggingJsonProcessor$setUpFormatter-614569086.zig:40)
at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:666)
at io.quarkus.runtime.Application.start(Application.java:101)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:98)
at java.base/java.lang.Thread.run(Thread.java:829)
由于某种原因,错误的方法(或两种方法?)似乎被覆盖了。
我怀疑它的发生是因为这些方法或多或少具有相同的签名。
有没有办法让 Kotlin 覆盖更精确以避免这个问题?
与我最初的假设相反,问题显然不是由 Kotlin 引起的,而是由 Quarkus 引起的。依赖注入似乎被非常相似的方法搞糊涂了。由于我无法更改任何方法名称或签名,因为它们来自第三方 Quarkiverse 库,因此我通过不再子类化 ExtFormatter
来解决这个问题,而是实例化它的一个已经存在的子类 JsonFormatter
:
import io.quarkiverse.loggingjson.JsonGenerator
import io.quarkiverse.loggingjson.JsonProvider
import org.jboss.logmanager.ExtLogRecord
import org.jboss.logmanager.formatters.JsonFormatter
[...]
class JsonLoggingProvider : JsonProvider {
private val jsonFormatter = JsonFormatter()
private fun writeMessage(generator: JsonGenerator, event: ExtLogRecord) {
val message = jsonFormatter.formatMessage(event)
[...]
}
}
再次感谢broot帮助我!