首页 > 解决方案 > 如何处理从 Java 到 Kotlin 的通用列表转换?

问题描述

在将 Java 代码重写为 Kotlin 的过程中,我需要定义一个列表的对象类型。问题是它未知的,它可以包含不同类型的对象。情况:

在我的 Java 类中,我定义了一个包含TopicNode对象的列表:private List<TopicNode> nodes. 这些对象可以包含一个类型的消息T extends Message。消息可以是 , 等类型BooleanInt32一个String节点看起来像:

主题节点.java

class TopicNode<T extends Message> extends AbstractNodeMain {
    // Implementation
}

包含此列表的 Java 类如下所示:

TopicControllerImpl.java

public class TopicControllerImpl implements TopicController {

    private List<TopicNode> nodes;

    @Override
    public void subscribe(String topic, Class type, Messenger subscriber) {
        TopicNode node = findOrCreateNode(topic, type);
        node.addListener(subscriber);
    }

    private <T extends Message> TopicNode<T> findNode(String topic) {
        for (TopicNode node : nodes) {
            if (node.getTopic().equals(topic)) {
                return (TopicNode<T>) node;
            }
        }
        return null;
    }

    private <T extends Message> TopicNode findOrCreateNode(String topic, Class<T> type) {
        TopicNode<T> node = findNode(topic);
        if (node != null) {
            return node;
        }
        // If node doesn't exist yet, create it, run it and add it to the collection
        node = new TopicNode<>(topic, type);
        executor.execute(node, configuration);
        nodes.add(node);
        return node;
    }
}

当我尝试在 Kotlin ( private val nodes: ArrayList<TopicNode> = ArrayList()) 中定义这样的列表时,编译器会说:One type argument expected for class TopicNode<T : Message>.

为了解决这个问题,您可以在 Kotlin 中定义如下所示的类和列表:

TopicControllerImpl.kt

class TopicControllerImpl<T : Message>(/** args */) : TopicController<T> {
    private val nodes: ArrayList<TopicNode<T>> = ArrayList()

    override fun subscribe(topic: String, type: Class<T>, subscriber: Messenger) {
        val node = findOrCreateNode(topic, type)
        node.addListener(subscriber)
    }

    private fun findNode(topic: String): TopicNode<T>? {
        return nodes.firstOrNull { it.topic == topic }
    }

    private fun findOrCreateNode(topic: String, type: Class<T>): TopicNode<T> 
    {
        var node = findNode(topic)
        if (node != null) {
            return node
        }
        // If node doesn't exist yet, create it, run it and add it to the collection
        node = TopicNode(topic, type)
        executor.execute(node, configuration)
        nodes.add(node)

        return node
    }
}

这样做的问题是您需要定义T用于列表的类型,TopicControllerImpl而这个未知并且在 Java 中不需要。未知的类型将Message是什么,它也可能会有所不同。

既然是这种情况,我该如何处理 Kotlin 中的这种情况?甚至可能吗?

提前非常感谢!

标签: javaandroidlistgenericskotlin

解决方案


这是泛型和通配符之间的区别。例如

private val nodes: ArrayList<TopicNode<T>> = ArrayList()

意味着我将拥有一个具有给定类型的泛型类的数组T。尽管

private val nodes: ArrayList<TopicNode<*>> = ArrayList()

意味着我将拥有一个混合类型的泛型类的数组。

如果您想使用第一个更改您的定义,但如果您想使用第二个更改您的数组声明。


推荐阅读