2

我有许多操作数据库的对象(不是类),我想制作一个更小的帮助类,这样我就可以做类似的事情java my.helper.class my.database.class并执行该run方法。

例如,这编译

trait A extends Runnable
class B extends A { def run() = println("run") }
object Test extends App {
  Class.forName(args(0)).newInstance().asInstanceOf[A].run()
}

然后做我所期望的。

$scala Test B
run

这也编译

trait A extends Runnable
object B extends A { def run() = println("run") }
object Test extends App {
  Class.forName(args(0)).newInstance().asInstanceOf[A].run()
}

但是会发生这种情况:

$scala Test B
java.lang.InstantiationException: B
    at java.lang.Class.newInstance(Class.java:418)
    at Test$.delayedEndpoint$Test$1(Test.scala:9)
    at Test$delayedInit$body.apply(Test.scala:8)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:383)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at Test$.main(Test.scala:8)
    at Test.main(Test.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:68)
    at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:99)
    at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:68)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:99)
    at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
    at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:94)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Caused by: java.lang.NoSuchMethodException: B.<init>()
    at java.lang.Class.getConstructor0(Class.java:2971)
    at java.lang.Class.newInstance(Class.java:403)
    ... 28 more

这是有道理的,我认为这会起作用:

$scala Test B$
java.lang.IllegalAccessException: Class Test$ can not access a member of class B$ with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101)
    at java.lang.Class.newInstance(Class.java:427)
    at Test$.delayedEndpoint$Test$1(Test.scala:9)
    at Test$delayedInit$body.apply(Test.scala:8)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:383)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at Test$.main(Test.scala:8)
    at Test.main(Test.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:68)
    at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:99)
    at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:68)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:99)
    at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
    at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:94)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

但它也失败了。我知道我可以将所有这些静态对象变成类,但这在这个应用程序中没有意义,所以我特意寻找优雅的方法来做到这一点。

4

1 回答 1

2

我个人认为最优雅的方法是不动态加载这样的东西。指定有效输入真的那么难吗?这为您的实例的A来源提供了更大的灵活性。

object Test extends App {
  args(0) match {
    case "B" => B
    case "C" => 
      val someOtherConfig = args(1)
      new C(someOtherParam)
    case other => throw new Exception("invalid input")
  } run
}

我会使用Scopt来解析参数

于 2014-05-28T17:37:26.280 回答