I have the following Scala class hierarchy:
abstract class BaseModule(val appConf : AppConfig) {
// ...
}
class SimpleModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
class FairlyComplexModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
// dozens of other BaseModule subclasses...
At runtime, my app will accept a String input argument for the fully-qualified class name of a BaseModule subclass to instantiate, but the code won't know which concrete subclass it will be. So I have:
val moduleFQCN = loadFromInputArgs() // ex: "com.example.myapp.SimpleModule"
val moduleClass = Class.forName(moduleFQCN)
println(s"Found ${moduleFQCN} on the runtime classpath.")
val module = Class.forName(moduleFQCN).getConstructor(classOf[AppConfig]).newInstance(appConf).asInstanceOf[BaseModule]
So this way, the input specifies which BaseModule subclass to look for on the classpath, and then subsequently, to instantiate. The first three lines above execute just fine, and I see the println fire. However the last line above throws an exception:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
<rest of stacktrace omitted for brevity>
So clearly I'm doing something wrong when trying to create an instance of the SimpleModule subclass, just can't figure out what it is. Any ideas?
You're probably failing because you call newInstance() without any arguments, but no default constructor is found therefore the instantiation fails.
try this:
Class.forName(moduleFQCN).getConstructor(classOf[AppConfig])
.newInstance(appConf).asInstanceOf[BaseModule]
Where appConf is an instance of AppConfig and is the parameter to instantiate BaseModule with.
Related
I defined a Scala class MyAnnotation, used to annotate certain classes within my program:
case class MyAnnotation() extends scala.annotation.StaticAnnotation {
println("MyAnnotation initialized") // doesn't get printed
}
Which is used in the following way:
#MyAnnotation()
class MyClass() {
...
}
However, when I instantiate the MyClass class, the constructor of MyAnnotation doesn't get executed. I.e., the println does not happen.
val x = new MyClass()
// nothing gets printed
Sumarized: is there any way to provide a constructor to a user-defined annotation class that gets executed when another class annotated with that annotation is instantiated?
I am a C++ programmer and is trying to learn Scala. I want to achieve something similar to the following code using C++ template
template<typename T>
class Foo {
public:
T* bar;
/////////////////Other Code Omitted//////////////////////////
};
Its counter-part in Scala will not compile due to type erasure
class Foo[E](){
val bar = new E() //Will not compile
}
I have been searching the whole night for a workaround, this seems to be one of them
package test
import scala.reflect._
object Type {
def newInstance[T: ClassTag](init_args: AnyRef*): T = {
classTag[T].runtimeClass.getConstructors.head.newInstance(init_args: _*).asInstanceOf[T]
}
}
class Foo[T1:ClassTag](init_args: AnyRef*){
val bar = Type.newInstance[T1](init_args)
}
class TestClass(val arg:String){
val data = arg
}
However, when I try to instantiate one (val test = new Foo[Test]("test")) in the scala console, it gives the following error
java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at ParActor.Type$.newInstance(ParActor.scala:32)
at ParActor.Foo.<init>(ParActor.scala:37)
... 35 elided
I am not exactly sure what causes the problem and how to fix this. Other work around is also welcomed.
You should turn
Type.newInstance[T1](init_args)
into
Type.newInstance[T1](init_args: _*)
What : _* does is turn a list or sequence into a varargs argument. A varargs parameter AnyRef* is actually an IndexedSeq[AnyRef], more specifically a WrappedArray[AnyRef]. So when you pass init_args as an argument to newInstance without telling the compiler to interpret it as a varargs argument you are actually passing in WrappedArray(WrappedArray("test")).
So I'm trying to create an instance of a class using following statements (simplified):
class A
classOf[A].newInstance()
The call throws:
java.lang.InstantiationException: A$A426$A$A426$A
Caused by: java.lang.NoSuchMethodException: A$A426$A$A426$A.<init>()
I did try defining init() method with different variations with no success. What am I missing?
Thanks in advance.
Related, didn't work for me:
No such method exception Hadoop <init>
This answer
I suspect your problem is that A is being declared inside anther class. See this example:
import org.specs2.mutable.Specification
class StackoverflowSpec extends Specification {
class B
"A" should {
"be instantiatable" in {
classOf[A].newInstance() must not(beNull)
}
}
"B" should {
"throw an instantiation exception" in {
classOf[B].newInstance must throwAn[InstantiationException]
}
}
}
class A
I think that what's happening is that in the jvm, your classes are A and StackoverflowSpec$B, and that StackoverflowSpec$B requires a StackoverflowSpec to be passed in to it's constructor, because it's an inner class.
Thanks for suggestion about inner class but actually it has to do with IntelliJ IDEA 'scala worksheet' -- scala sandbox file with interactive evaluation. For some reason, instantiation described above throws only in a worksheet, it does work in a regular Scala REPL.
Sorry for the broad topic; I'm just not quite sure what I'm doing wrong.
I have a class structure
trait BaseType {
val property: String
}
trait MiddleTrait extends BaseType {
val myProperty = property.length.toString
def userProperty() = {
myProperty
}
}
object Top extends MiddleTrait {
val property = "value given here"
}
Which compiles; but hits a run time error - java.lang.RuntimeException: java.lang.NoClassDefFoundError: Could not initialize class controllers.test.Top$
Updating MiddleTrait to def myProperty = property.length.toString it will run fine.
I looking to understand the theory behind this better so I could predict the error without seeing it fail at run time first
Thanks
When I paste your code into a Scala 2.11.6 REPL I don't get any errors at first. Trying to access myProperty will result in a NullPointerException
scala> Top.myProperty
java.lang.NullPointerException
at MiddleTrait$class.$init$(<console>:12)
... 35 elided
The NullPointerException is thrown because MiddleTrait gets initialized before Top at which point property is still null (see spec on template evaluation). If you turn myProperty into a function, the error goes away because the function is called on the fully initialized Top.
The error you quoted comes up for me when I try to access myProperty again, after the NullPointerException
scala> Top.myProperty
java.lang.NoClassDefFoundError: Could not initialize class Top$
... 33 elided
I'm currently constructing loggers (with configgy) like this:
class MyClass {
private val log = Logger.get(classOf[MyClass])
}
I would like to avoid repeating "MyClass" as in classOf[MyClass] (for example I want to quickly copy paste the log definition line, without smart IDE expanding the template with the class name), but I don't want to use the dynamic class of the current object, like:
class MyClass {
private val log = Logger.get(this.getClass)
}
EDIT: because this way instances of subclasses will have the subclass class object passed to the parent logger:
class MyClass {
private val log = Logger.get(this.getClass)
def doit = log.info("doing")
}
class SubClass extends MyClass {
}
new SubClass().doit
will use the logger configured for SubClass, not MyClass as I want.
Is there a way to have some fixed expression which somehow yields the class which is being defined at that point?
The short answer is that Scala doesn't have a way to do that. The long answer is that you can do it, but it's an ugly hack. The hack is to use the fact that exception stack traces include the name of the static class definition where the stack trace was created. Parse and tada. But, seriously, don't do this. Or, if you do, move it to a mixin trait and modify the parsing bit to pull the class name from the appropriate spot in the trace. Also, I've only tested this in some fairly limited conditions: no guarantee that it will work everywhere.
class MyClass {
private val log = Logger get (Class forName (
new RuntimeException().getStackTrace.apply(0).toString takeWhile
(_ != '(') split "\\." dropRight 1 mkString "."))
def doit = log.info("doing")
}
Surely you can just use the protected access modifier and access it directly?
class MyClass {
protected val log = Logger.get(classOf[MyClass])
}
class SubClass extends MyClass {
}
new SubClass().doit