0

Here is my code

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)
  }
}

and I got this:

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)

by the way,How could I get a type when I get a string name. I have an "int" and I want to pass type Int as the type parameter for generic

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
loner233
  • 13
  • 5
  • 1
    Reflection at runtime is not recommended. – cchantep Nov 27 '19 at 09:28
  • First **reflection** is a bad idea, is slow and unsafe, why do you need it? Why not just instantiating the class on code. PS: Lately there had been a couple of similar questions, are they related in anyway? Same project? - Second, `asInstanceOf` is a big **code smell** especially in this case it seems it will never work. - Finally, how did you expect it to work if you passed an **Int** and asked for a **Float**? – Luis Miguel Mejía Suárez Nov 27 '19 at 11:38
  • 1
    @LuisMiguelMejíaSuárez "Finally, how did you expect it to work if you passed an `Int` and asked for a `Float`?" `Int` is passed to `def someMethod(a: Int)...` and `Float` is `T` in `Word2Vec[T]`. There's no problem in casting `scala.Int` to `scala.Float`: `123.asInstanceOf[Float]`. It's `java.lang.Integer` that can't be casted to `java.lang.Float`. – Dmytro Mitin Nov 27 '19 at 19:14

1 Answers1

1

The following code with Int doesn't throw exception

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

or with _

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

Actually Class.forName + newInstance is not Scala reflection, it's Java reflection used in Scala. Scala reflection is different.

by the way,How could I get a type when I get a string name. I have an "int" and I want to pass type Int as the type parameter for generic

I'm not sure this can be done with Java reflection. With Scala reflection

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]
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66