Using reflection to access an outer class in Scala

In Scala, can reflection be used to access the outer class of the inner class? For instance:

class A { val inner = new { println(getClass.getConstructors.toList) println(getClass.getDeclaredFields.toList) } } scala> val a = new A List(public $line11.$read$$iw$$iw$A$$anon$1($line11.$read$$iw$$iw$A)) List() a: A = A@45f76fc7 

I think the Scala compiler keeps a reference to an external class somewhere, but you can see here that the list of fields printed in the constructor is empty. In addition, it seems that the constructor is referencing an instance of an external class (but itโ€™s hard to say for sure --- I donโ€™t know exactly what is going on here). I also noticed that in some cases there is a $outer field, which seems to be what I need, but it is not always there, and I do not understand this.

WHY!!!!!! I have an inner class that I need to create a new instance of using reflection. The new instance is copied from the existing instance and must have the same external link.

+4
source share
3 answers

I do not think that you can reliably get a parent if you do not use the parent outside the constructor, if the inner class. Given:

 class X { val str = "xxyy" val self = this val inner = new { override def toString():String = { "inner " + self.toString } } override def toString():String = { "ima x" + this.str } } 

If you do javap you get a private $ external field

but given:

 class X { val str = "xxyy" val self = this val inner = new { println(self) } override def toString():String = { "ima x" + this.str } } 

javap does not specify an external field $.

+5
source

If you know that you need it, then itโ€™s better (far) to make the link explicit and completely avoid reflection:

 class A { outerA => val inner = new { val outer = outerA println(getClass.getConstructors.toList) println(getClass.getDeclaredFields.toList) } } 

The magic sauce here is the type self outerA => , which allows you to give a unique name to the this help system.

+5
source

Inner classes MUST have a reference to their outer class. This is implied by the JVM. In the following example, the call to new InnerClass() translates to new InnerClass(this) . OuterClass instance is stored in the $outer field in the inner class, which can be accessed using this OuterClass.this syntax.

 class OuterClass { val str = "abcde"; val inner = new InnerClass(); class InnerClass { def printStr() { println(OuterClass.this.str); } } } 

To build a new InnerClass instance using reflections, you must have a reference to the OuterClass instance. To create a new instance, follow these steps:

 val outer = new OuterClass; val newInner = outer.inner.getClass.getDeclaredConstructor(classOf[OuterClass]) .newInstance(outer); 

In addition, I would say that creating a new inner class using reflections sounds like a pretty bad coding practice. Only OuterClass should ever see InnerClass instances and therefore should be prepared for any situation where it might need to create a new InnerClass instance. If other classes have InnerClass visibility, then you need to rebuild it into your class.

+4
source

All Articles