You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何引用Any类型类的变量以避免未解析引用

解决方案

情况1:可修改目标类源码

定义一个包含所需字段的接口,让所有相关类实现该接口,从根源上解决编译类型问题:

// 定义统一接口,包含所有需要访问的字段
interface BarData {
    val unixSecond: Long
    val open: Double
    val high: Double
    val low: Double
    val close: Double
    val volume: Double
}

// 让所有需要处理的类实现这个接口(示例)
class Algobar(
    override val unixSecond: Long,
    override val open: Double,
    override val high: Double,
    override val low: Double,
    override val close: Double,
    override val volume: Double,
    // 其他自定义字段
) : BarData

class ThirdPartyBar(
    override val unixSecond: Long,
    override val open: Double,
    override val high: Double,
    override val low: Double,
    override val close: Double,
    override val volume: Double,
    // 第三方类原有字段
) : BarData

修改函数参数类型为List<BarData?>,编译时即可正常访问字段,同时替换原代码中语义不符的map为forEach(仅执行副作用无需返回新列表):

fun createTA4JBarsFromAlgobars(timebars: List<BarData?>, name: String): BaseBarSeries? {
    val series = BaseBarSeriesBuilder().withName(name).build()
    
    timebars.forEach { bar ->
        bar?.let {
            series.addBar(
                utilService.unixtimeToZoneDateTime(it.unixSecond),
                it.open,
                it.high,
                it.low,
                it.close,
                it.volume
            )
        }
    }
    
    return series
}

情况2:无法修改目标类源码(如第三方类)

方法A:类型判断+智能转换

如果已知所有可能的类类型,通过when分支做类型判断,Kotlin会自动进行智能转换,保证编译安全:

fun createTA4JBarsFromAlgobars(timebars: List<Any?>, name: String): BaseBarSeries? {
    val series = BaseBarSeriesBuilder().withName(name).build()
    
    timebars.forEach { item ->
        when (item) {
            is Algobar -> addBarToSeries(series, item)
            is ThirdPartyBar -> addBarToSeries(series, item)
            // 后续新增类型只需添加对应分支
        }
    }
    
    return series
}

// 提取公共逻辑,避免代码重复
private fun addBarToSeries(series: BaseBarSeries, bar: Any) {
    when (bar) {
        is Algobar -> series.addBar(
            utilService.unixtimeToZoneDateTime(bar.unixSecond),
            bar.open, bar.high, bar.low, bar.close, bar.volume
        )
        is ThirdPartyBar -> series.addBar(
            utilService.unixtimeToZoneDateTime(bar.unixSecond),
            bar.open, bar.high, bar.low, bar.close, bar.volume
        )
    }
}

方法B:反射统一处理

如果类数量多或类型不确定,可通过Kotlin反射动态获取字段值(注意:反射有性能开销,需确保字段名称和类型完全匹配):

import kotlin.reflect.full.memberProperties

fun createTA4JBarsFromAlgobars(timebars: List<Any?>, name: String): BaseBarSeries? {
    val series = BaseBarSeriesBuilder().withName(name).build()
    
    timebars.forEach { item ->
        item?.let { obj ->
            // 反射获取字段值并做类型转换
            val unixSecond = obj::class.memberProperties.find { it.name == "unixSecond" }?.get(obj) as? Long
            val open = obj::class.memberProperties.find { it.name == "open" }?.get(obj) as? Double
            val high = obj::class.memberProperties.find { it.name == "high" }?.get(obj) as? Double
            val low = obj::class.memberProperties.find { it.name == "low" }?.get(obj) as? Double
            val close = obj::class.memberProperties.find { it.name == "close" }?.get(obj) as? Double
            val volume = obj::class.memberProperties.find { it.name == "volume" }?.get(obj) as? Double

            // 所有字段非空时才添加
            if (unixSecond != null && open != null && high != null && low != null && close != null && volume != null) {
                series.addBar(
                    utilService.unixtimeToZoneDateTime(unixSecond),
                    open, high, low, close, volume
                )
            }
        }
    }
    
    return series
}

内容的提问来源于stack exchange,提问作者Joachim Karlsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:40:45