我想使用以下类实例化一个新对象:
class Test[T : ClassTag](val value : T) extends Serializable
private object Test {
private var testClass : Class[_] = _
def setTestClass(test : Class[_]) : Unit = {
testClass = test
}
def apply[T : ClassTag](value : T) : Test[T] = {
testClass.getConstructors()(0).newInstance(value).asInstanceOf[Test[T]]
}
}
class Subtest[T : ClassTag](
override val value : T,
val additional : Integer
) extends Test[T](value)
我在某处设置了带有 setTestClass
的测试类,该类已从字符串中加载了Class.forName
。假设它是"Subtest"
.我希望使用 - 例如以下代码实例化一个新Subtest[String]
:
Test("my random string") // It should return a new Subtest[String]
问题是newInstance
抛出java.lang.IllegalArgumentException: wrong number of arguments
.我已经检查了Constructor
的parameterTypes
,有两种参数类型:
- 类 java.lang.Object
- interface scala.reflect.ClassTag
好。如何提供类标签?这里有什么问题?有没有更好的方法,解决方法?
T: ClassTag
语法称为上下文绑定。 它是类型为 ClassTag[T]
的隐式参数的语法糖。 换句话说,以下类签名是等效的:
class Test[T : ClassTag](val value : T)
class Test[T](val value: T)(implicit val ev: ClassTag[T])
因此,您要查找的构造函数需要另一个参数。 使用上下文绑定语法时,始终可以使用 implicitly
来获取所需的参数(由于上下文绑定的语义,该参数保证存在)。 或者,您可以使用 classTag
运算符在知道 ClassTag[T]
实例可用时直接获取该实例。
另一个细节是,在这样的对象中使用类型参数时,它需要是一个 AnyRef
.
因此,您的apply
方法可能如下所示:
def apply[T <: AnyRef : ClassTag](value : T) : Test[T] = {
testClass.getConstructors.head.newInstance(value, classTag[T]).asInstanceOf[Test[T]]
}