gpt4 book ai didi

java - Kotlin 与 Java 嵌套泛型

转载 作者:太空狗 更新时间:2023-10-29 13:49:31 26 4
gpt4 key购买 nike

我在尝试将带有嵌套泛型的 Java 代码转换为 Kotlin 时遇到了一些麻烦。以这个Java SSCCE为例(注意S和T的关系):

public class JavaTest {

private class JavaObjectContainer<S> {
public S obj;
}

private abstract class JavaSampleClass<S, T extends JavaObjectContainer<S>> {
private Class<S> type;

public JavaSampleClass(Class<S> type) {
this.type = type;
}

public Class<S> getType() {
return type;
}

public abstract void callMethod(S s);
}

private class JavaChildSampleClass extends JavaSampleClass<String, JavaObjectContainer<String>> {
public JavaChildSampleClass() {
super(String.class);
}

@Override
public void callMethod(String s) {}
}

private class JavaTestContainer {
private Map<Class<?>, JavaSampleClass> sampleClasses;

public JavaTestContainer() {
this.sampleClasses = new HashMap<>();
}

public void registerJavaSampleClass(JavaSampleClass javaSampleClass) {
sampleClasses.put(javaSampleClass.getType(), javaSampleClass);
}

public void callMethod(Object obj) {
sampleClasses.get(obj.getClass()).callMethod(obj);
}
}

public void test() {
JavaTestContainer javaTestContainer = new JavaTestContainer();

javaTestContainer.registerJavaSampleClass(new JavaChildSampleClass());

javaTestContainer.callMethod("Hola");
}

}

将此 SSCCE 视为通用工厂模式的实现,其中用户注册多个 JavaSampleClass,其方法可在未来调用。

由于 Kotlin 没有提供通配符的替代方案,我尝试了以下方法:

class KotlinTest {

private class KotlinObjectContainer<S> {
var obj : S? = null
}

private open class KotlinSampleClass<S, T : KotlinObjectContainer<S>>(var type: Class<S>) {

fun callMethod(s : S) {}
}

private class KotlinChildSampleClass : KotlinSampleClass<String, KotlinObjectContainer<String>>(String::class.java)

private inner class KotlinTestContainer {
private val sampleClasses: MutableMap<Class<Any>, KotlinSampleClass<Any, KotlinObjectContainer<Any>>> = mutableMapOf()

fun registerKotlinSampleClass(kotlinSampleClass: KotlinSampleClass<Any, KotlinObjectContainer<Any>>) {
sampleClasses.put(kotlinSampleClass.type, kotlinSampleClass)
}

fun callMethod(obj : Any) {
sampleClasses[obj.javaClass]?.callMethod(obj)
}
}

fun test() {
val kotlinTestContainer = KotlinTestContainer()

// Exception!
kotlinTestContainer.registerKotlinSampleClass(KotlinChildSampleClass())

kotlinTestContainer.callMethod("Hello")
}

}

以上代码在IDE中抛出如下异常:

Type mismatch.
Required: KotlinTest.KotlinSampleClass<Any, KotlinObjectContainer<Any>>
Found: KotlinTest.KotlinChildSampleClass

我一直在考虑将 sampleClasses 映射声明为

MutableMap<*, *>

但是,我该如何初始化它呢?此外,由于 * 表示投影外的参数,因此在尝试将新值放入 map 时,IDE 会向我显示错误。

我该如何克服这个问题?我很确定我遗漏了一些东西......

最佳答案

As Kotlin does not provide an alternative to wildcards...

I have been thinking of declaring sampleClasses map as

MutableMap<*, *>

对于这种情况*非常适合通配符。如果你有 Class<?>在 Java 中,你需要 Class<*>在 Kotlin 中,不是 Class<Any>* .

private val sampleClasses: MutableMap<Class<*>, KotlinSampleClass<*, *>> = mutableMapOf()

fun registerKotlinSampleClass(kotlinSampleClass: KotlinSampleClass<*, *>) {
sampleClasses.put(kotlinSampleClass.type, kotlinSampleClass)
}

@Suppress("UNCHECKED_CAST")
fun callMethod(obj : Any) {
(sampleClasses[obj.javaClass] as KotlinSampleClass<Any, *>?)?.callMethod(obj)
}

您不需要在 callMethod 中进行强制转换的唯一原因在 Java 中是因为您使用的是原始类型(正如 Turing85 的评论中提到的那样)并且编译器基本上放弃了类型检查。

关于java - Kotlin 与 Java 嵌套泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49860648/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com