如何通过scala反射创建带有类型参数的实例?

时间:2019-11-27 09:19:04

标签: scala reflection scala-reflect

这是我的代码

package a1

trait Algorithm[T] {
  def someMethod(a: Int): T
}
package b2

import a1.Algorithm

class Word2Vec[T] extends Algorithm[T] {
  def someMethod(a: Int): T = a.asInstanceOf[T]
}
package c3

import a1.Algorithm

object Main {
  def main(args:Array[String]) = {
    val word2vec:Algorithm[Float] = Class.forName("b2.Word2Vec").newInstance().asInstanceOf[Algorithm[Float]]
    val a = word2vec.someMethod(123)
    println(a)
  }
}

我明白了:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Float
    at scala.runtime.BoxesRunTime.unboxToFloat(BoxesRunTime.java:107)
    at c3.Main$.main(Main.scala:8)
    at c3.Main.main(Main.scala)

顺便说一句,当我得到一个字符串名称时,如何获得一个类型。我有一个"int",我想将类型Int作为泛型的类型参数

1 个答案:

答案 0 :(得分:1)

以下带有Int的代码不会引发异常

val word2vec = Class.forName("b2.Word2Vec").newInstance().asInstanceOf[Algorithm[Int]]
val a = word2vec.someMethod(123)
println(a) // 123

或带有_

val word2vec = Class.forName("b2.Word2Vec").newInstance().asInstanceOf[Algorithm[_]]
val a = word2vec.someMethod(123)
println(a) // 123

实际上Class.forName + newInstance不是Scala反射,它是Scala中使用的Java反射。 Scala反射是不同的。

  

顺便说一句,当我得到一个字符串名称时,如何获得一个类型。我有一个   “ int”,我想将Int类型作为泛型的类型参数

我不确定这可以通过Java反射来完成。使用Scala反射

import scala.reflect.runtime.universe._
val mirror = runtimeMirror(this.getClass.getClassLoader)
val classSymbol = mirror.staticClass("b2.Word2Vec") // class Word2Vec
// if string is "int"
internal.typeRef(NoPrefix, classSymbol, List(typeOf[Int])) // Word2Vec[Int]
// if string is "float"
internal.typeRef(NoPrefix, classSymbol, List(typeOf[Float])) // Word2Vec[Float]