Java 如何在使用泛型时修复此未经检查的强制转换错误?

Java 如何在使用泛型时修复此未经检查的强制转换错误?,java,list,generics,kotlin,Java,List,Generics,Kotlin,在我的类中,我有一个包含主题节点的列表。这些列表的节点应该从Message类扩展。在节点列表中的方法findNode中,搜索具有特定主题的节点,如果该节点匹配,则返回该节点。Java编译器抱怨TopicNode被转换为T类型的TopicNode,因为它可能不是T类型。解决这个问题的最好办法是什么 private val nodes: MutableList<TopicNode<*>> init { this.nodes = ArrayList() } priv

在我的类中,我有一个包含主题节点的列表。这些列表的节点应该从Message类扩展。在节点列表中的方法
findNode
中,搜索具有特定主题的节点,如果该节点匹配,则返回该节点。Java编译器抱怨TopicNode被转换为
T
类型的TopicNode,因为它可能不是
T
类型。解决这个问题的最好办法是什么

private val nodes: MutableList<TopicNode<*>>

init {
    this.nodes = ArrayList()
}

private fun <T : Message> findNode(topic: String): TopicNode<T>? {
    for (node in nodes) {
        if (node.topic == topic) {
            return node as TopicNode<T> // Unchecked cast: TopicNode<*> to TopicNode<T>
        }
    }
    return null
}
private val节点:可变列表
初始化{
this.nodes=ArrayList()
}
private fun findNode(主题:字符串):TopicNode?{
用于(节点中的节点){
if(node.topic==topic){
将节点作为TopicNode返回//未选中强制转换:TopicNode到TopicNode
}
}
返回空
}

我想我自己找到了解决方案。您可以使用
.filterIsInstance()
来筛选列表中
T
类型的项目

这将导致以下解决方案:

 private fun <T : Message> findNode(topic: String): TopicNode<T>? {
    val messageNodes: List<TopicNode<T>> = nodes.filterIsInstance<TopicNode<T>>()
    for (node in messageNodes) {
        if (node.topic == topic) {
            return node
        }
    }
    return null
}
private fun findNode(主题:String):TopicNode?{
val messageNodes:List=nodes.filterIsInstance()
for(messageNodes中的节点){
if(node.topic==topic){
返回节点
}
}
返回空
}

它检查列表中是否有
TopicNode
类型的项,其中
T
Message
扩展而来。我怀疑这应该是类的参数化,而不是方法的参数化

问题中的代码必须来自未显示的类。该类的每个实例都包含一个节点列表。从方法判断,每个类都包含特定消息类型的节点。但是方法a)要求调用方提前知道哪种类型,和b)允许在同一实例上为不同类型调用它,这毫无意义

相反,您可以告诉编译器每个实例都持有特定类型的节点,方法是在类上提供一个类型参数,而不是方法:

class MyClass<T : Message> {
    private val nodes: MutableList<TopicNode<T>>

    init {
        this.nodes = ArrayList()
    }

    private fun findNode(topic: String): TopicNode<T>? {
        for (node in nodes) {
            if (node.topic == topic) {
                return node // No need to cast
            }
        }
        return null
    }
}
class-MyClass{
私有val节点:可变列表
初始化{
this.nodes=ArrayList()
}
private fun findNode(主题:字符串):TopicNode{
用于(节点中的节点){
if(node.topic==topic){
返回节点//无需强制转换
}
}
返回空
}
}
这样,该方法已经知道其节点的类型,并且可以直接返回它们

事实上,该类可以简化为:

class MyClass<T : Message> {
    private val nodes: MutableList<TopicNode<T>> = ArrayList()

    private fun findNode(topic: String)
        = nodes.find{ it.topic == topic }
}
class-MyClass{
私有val节点:MutableList=ArrayList()
private fun findNode(主题:字符串)
=节点。查找{it.topic==topic}
}

把它放在那里,以防万一它适合OP的用例,并且他们不需要列表上的“扩展泛型”。有时你看不见森林,只看到树木

private val nodes: MutableList<TopicNode<Message>>

private fun findNode(topic: String) = nodes.firstOrNull{ it.topic == topic}
它对该类有一系列限制。有关该主题的更多信息


我确实觉得评论中的问题很有趣:如何定义列表中的对象应该从另一个类扩展?不确定如果不按照gidds在其回答中所做的路线执行,是否可以执行此操作

这些列表的节点应该从消息类扩展。-为什么要使用
呢?也许接下来的问题应该是:
如何定义列表中的对象应该从另一个类扩展?
我不知道怎么做@timcastelijn您的代码可以写成:
return nodes.filterIsInstance().firstOrNull{it.topic==topic}
inkotlin@Klyner您正在寻找一个特定的元素,但是您事先过滤了整个列表。这将更短:
private fun findNode(主题:String)=nodes.firstOrNull{(它作为?TopicNode)?.topic==topic}
,并且只需要一次迭代。但是很明显,如果
节点
属于
可变列表类型
看起来是一个很好的解决方案,那么原始问题仍然存在。但是将
消息
指定为
主题节点
的类型是一个好主意吗?是否可以将扩展自
Message
的主题节点
MyMessage
添加到列表中?
class TopicNode<Out T> {