I am playing with reflection to achieve a deep analysis on a trait. One of the things I would like to get is the initial value set to a member field. For example, in the trait:
trait A {
val x: Int = 3
val y: String = "y"
}
it would be nice to know 3 and "y". I have not found anything related to this task in the API, and due to the following output (generated by scalac -Xprint):
abstract trait A extends Object {
<accessor> def com$hablapps$A$_setter_$x_=(x$1: Int): Unit;
<accessor> def com$hablapps$A$_setter_$y_=(x$1: String): Unit;
<stable> <accessor> def x(): Int;
<stable> <accessor> def y(): String
};
abstract trait A$class extends {
def /*A$class*/$init$($this: com.hablapps.A): Unit = {
$this.com$hablapps$A$_setter_$x_=(3);
$this.com$hablapps$A$_setter_$y_=("y");
()
}
}
I am afraid it is going to be quite hard to access them, since they are kept in the $init$ method's body. Is there any (easy) way to get those values with reflection?
You have to disassemble the bytecode:
trait A { val x: Int = 3 }
public abstract class A$class extends java.lang.Object{
public static void $init$(A);
Code:
0: aload_0
1: iconst_3
2: invokeinterface #12, 2; //InterfaceMethod A.A$_setter_$x_$eq:(I)V
7: return
See line 1--the only place the value exists is in the bytecode for the init method!
You cannot get to this any other way, since if you have
trait A { val x: Int = 3 }
trait B extends A { override val x = 7 }
class C extends B {}
you find that C
extends A$_setter_$x_$eq
to do nothing at all--making the A$class.$init$
call a no-op and rendering the value unretrievable.
Proof:
public class C extends java.lang.Object implements B,scala.ScalaObject{
public void A$_setter_$x_$eq(int);
Code:
0: return
public void B$_setter_$x_$eq(int);
Code:
0: aload_0
1: iload_1
2: putfield #11; //Field x:I
5: return
I doubt you can introspect to this point. That's not information about the type, but code. If you have the tree for the trait, you can find it out, but, otherwise, I doubt it.
You can use, however, class file parsers to investigate this further. I assume these would appear as constants for the class, which can be read. I'm not sure you could associate them with the variable, but...
I'm not much familiar with class file parsers, but I think a tool called "asm" does that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With