在scala 2.10中通过java反射调用构造函数

时间:2013-01-18 14:19:15

标签: scala reflection scala-2.10

在Scala 2.10之前我有

class A {
    class B(b: Int) {
    }
}

在代码中的某处用

重新创建B类
val bCtor = bInstance.getClass.getConstructor(classOf[Int])
bCtor.newInstance ...

一切都很好。这是签名public A$B(Int)

现在构造函数有2个!!!参数。它有一个新的签名public A$B(A,Int)。 A型的论点是什么?我没有从我的函数访问A类。有任何解决方法吗?

例如newInstance with arguments - 它不再适用于内部类

4 个答案:

答案 0 :(得分:3)

请注意不要将java内部类与scala路径依赖类型混淆 (来自Programming In ScalaBook):

  

路径依赖类型类似于Java中内部类类型的语法,但有一个至关重要的区别:路径依赖类型命名外部对象,而内部类类型命名为外

因此,在您的情况下,bInstance与aInstance相关。

我的假设是aInstance是作为第一个参数传递给此构造函数的对象。

答案 1 :(得分:1)

您可以使用无约束的自我类型注释来引用A的this版本,即使是在B内(其中this现在指的是B实例)。

package rrs.scribble

object  OuterInner {
  class Outer { oThis =>
    class Inner {
      def identify { printf("I am %s; I'm inside of %s%n", this, oThis) }
    }
    val inner = new Inner
  }

  def oiTest {
    val o1 = new Outer
    o1.inner.identify
  }
}

在REPL中:

Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).

scala> import rrs.scribble.OuterInner._
import rrs.scribble.OuterInner._

scala> oiTest
I am rrs.scribble.OuterInner$Outer$Inner@63d0d313; I'm inside of rrs.scribble.OuterInner$Outer@22d1b797

答案 2 :(得分:1)

首先,添加A作为第一个构造函数参数也是它在Java中的工作方式:

  
    

If this Class object represents an inner class declared in a non-static context, the formal parameter types include the explicit enclosing instance as the first parameter.

  

其次,

  

A型的争论是什么?我没有从我的函数访问A类。

如果您有一个B(如您的示例所示),那么您可以access its enclosing instance(它似乎没有正式记录,因此可能会在将来的Java版本中更改) :

val aInstance = bInstance.getClass.getDeclaredField("this$0").get(bInstance)
bCtor.newInstance(aInstance, ...)

如果不这样做,则无法创建B(没有A),但您无法创建class A(foo: Int) { class B { def bar = foo } } classOf[A#B].getConstructor().newInstance().bar 。您希望此代码返回什么?

{{1}}

答案 3 :(得分:0)

@evantill是对的,B的唯一构造函数是A$B.<init>(A, Int)。所以bInstance.getClass.getConstructor(classOf[A], classOf[Int])有效。