1

I've got the following Scala code and although debugging it, and checking what does method createObject proves everything is ok, I get an exception:

java.lang.IllegalArgumentException: wrong number of arguments
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)

in line constructor.newInstance(convertedArguments).asInstanceOf[T]

object ObjectFactory {
  def runTest() = {
    val container = createContainer("n1 | 1 | true")
    container.created
  }

  def createContainer(s: String): Container = {
    createObject(classOf[Container], s)
  }

  def createObject[T](cls: Class[T], line: String): T = {
    // we assume the classes first non-zero
    // argument constructor is the one we need :)
    val constructor = cls.getConstructors.filter(_.getParameterTypes.length > 0)(0)
    var ptypes = constructor.getParameterTypes

    val tokens: Array[String] = line.split("\\|", -1)
    val convertedArguments = tokens.zip(ptypes).collect {
      case Tuple2(value: String, propType: Class[_]) => convert(value.trim, propType)
    }.collect {
      case Some(o) => o
      case None    => null
    }

    constructor.newInstance(convertedArguments).asInstanceOf[T]
  }

  private def convert[T](input: String, outputClass: Class[T]): Option[T] = {
    if (outputClass == classOf[Date]) {
      Some(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S").parse(input).asInstanceOf[T])
    } else if (outputClass == classOf[BigDecimal]) {
      Some(BigDecimal.apply(input).asInstanceOf[T])
    }
    else {
        if (input == null || ("" == input) || ("null" == input))
          None
        else
          Some(outputClass.getConstructor(classOf[String]).newInstance(input))
    }
  }
}

class Container(val name: String, val score: Integer, val created: String)

What is happening here? How can I correct the code to be more scala-like - especially the type conversion parts.

1 Answer 1

2

Method newInstance takes varargs (AnyRef*), not Array[Any]. You are trying to call constructor with 1 argument - Array.

You should convert Array[Any] to Array[AnyRef] and than call method with special syntax : _*:

constructor.newInstance(convertedArguments.map{_.asInstanceOf[AnyRef]}: _*)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! This worked, although I had to add .asInstance[T] at the end :) Do you have some suggestions about type conversion I'm doing in this piece of code?
@MarcinCylke: There is only one thing I can tell about your code: you should use well-tested serializer. Or parsers for closed set of classes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.