如何用Kotlin/Java代码将Kotlin/Java Set转为Scala不可变Set
Kotlin/Java 环境无额外Scala依赖实现Set转Scala不可变Set
核心问题
- 直接调用
scala.collection.JavaConversions.asScalaSet转换得到的是scala.collection.mutable.Set(可变集合),无法满足需要不可变Set的入参要求 - 约束条件:项目不能引入Scala相关依赖、Scala编译插件,仅通过运行时调用Scala标准库自带逻辑完成转换,适配外部仓库Scala父类的继承需求
实现原理
Scala所有可变集合都自带toSet()方法,调用后会返回对应的scala.collection.immutable.Set不可变实例。全程通过反射调用相关方法,代码中不需要引入任何Scala类的import,不会产生编译期Scala依赖。
代码实现
Java版本
import java.util.Set; import java.lang.reflect.Method; public class ScalaImmutableSetConverter { public static Object convert(Set<?> jvmSet) throws Exception { // 反射获取Scala JavaConversions单例对象 Class<?> conversionsClz = Class.forName("scala.collection.JavaConversions$"); Object conversionsInstance = conversionsClz.getField("MODULE$").get(null); // 调用asScalaSet得到可变Scala Set Method asScalaSet = conversionsClz.getMethod("asScalaSet", Set.class); Object mutableSet = asScalaSet.invoke(conversionsInstance, jvmSet); // 调用toSet得到不可变Scala Set Method toImmutableSet = mutableSet.getClass().getMethod("toSet"); return toImmutableSet.invoke(mutableSet); } }
Kotlin版本
import java.util.Set private fun Any.invokeMethod(name: String, vararg args: Any?): Any? { val argTypes = args.map { it?.javaClass ?: Any::class.java }.toTypedArray() return this.javaClass.getMethod(name, *argTypes).invoke(this, *args) } fun <T> Set<T>.toScalaImmutableSet(): Any { val scalaConversions = Class.forName("scala.collection.JavaConversions$") .getField("MODULE$").get(null) val mutableScalaSet = scalaConversions.invokeMethod("asScalaSet", this)!! return mutableScalaSet.invokeMethod("toSet")!! }
注意事项
- 转换得到的对象可以直接作为参数传给Scala父类中要求不可变Set的方法,不需要额外处理
- 不要尝试将asScalaSet返回的可变Set强转为不可变Set类型,会抛出类型转换异常,必须通过
toSet()方法完成实际转换 - 整个实现仅在运行时调用Scala标准库方法,编译期不依赖任何Scala组件,不需要在项目中添加Scala插件或依赖包
内容的提问来源于stack exchange,提问作者tw_ob
相关产品推荐
相关产品推荐

