7

I have been experimenting with Manifests and such in Scala, and I am having a very hard finding a way to use an object's fields when accessed via the getDeclaredFields method...

Here is an example:

class Woah(val x: String, val y: String)

val w = new Woah("w_x", "w_y")
classOf[Woah].getDeclaredFields foreach (field => println(field.get(w))

I have tried many variations, such as creating a method inside of the class Woah that performs that same action as the third line of code, but replace field.get(w) with field.get(this), and it shows the same exception. The exception thrown is:

java.lang.IllegalAccessException: Class Fun$Woah$$anonfun$1 can not access a member of class Fun$Woah with modifiers "private final"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
    at java.lang.reflect.Field.doSecurityCheck(Field.java:960)
    at java.lang.reflect.Field.getFieldAccessor(Field.java:896)
    at java.lang.reflect.Field.get(Field.java:358)
    at Fun$Woah$$anonfun$1.apply(Fun.scala:17)
    at Fun$Woah$$anonfun$1.apply(Fun.scala:17)
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
    at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:35)
    at Fun$Woah.<init>(Fun.scala:17)
    at Fun$.main(Fun.scala:20)
    at Fun.main(Fun.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:81)
    at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:86)
    at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:81)
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:86)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:83)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

I have done as much searching as I can, and I am not finding any new ideas at the moment. From what I could find, the vals "x" and "y" in the class Woah are declared as private final because they are used outside of the constructor. So I also tried this:

class Woah(val x: String, val y: String) {
  def printParams = classOf[Woah].getDeclaredFields foreach { field =>
    println(field.get(this))
  }
}

Unfortunately the same exception is thrown. Is there any way to have the two vals be public? Or is it possible to accomplish the same goal through another avenue? I am simply interested in accessing a collection of a class's fields' values.

Thank you in advance for your help!

2 Answers 2

14
class Woah(val x: String, val y: String) {
  def printParams = classOf[Woah].getDeclaredFields foreach { field =>
    field.setAccessible(true)
    println(field.get(this))
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I'm not really familiar with the setAccessible methods, but wouldn't it be cleaner to keep the initial value of accessible and put it back after the println ?
@Nicolas: Yes, that's likely a good idea. I've only really used it in tests, and haven't bothered, but in production code, you probably want it restored.
0

All JVM fields in Scala are private. Access to them is made only through getters, in Scala, so that there's no distinction between them and a parameterless method.

Comments

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.