3

In Java, at runtime it's possible to access a private field using reflection and also a private nested/inner class using reflection (e.g. see here). Is there any specific technical reason, or any general design philosophy, that explains why Java is like this? I don't know but from reading this it looks like for C#/.NET, at least in some configurations, the same thing is not possible. Does Java also have that flexibility? Are there any JVM implementations where this is not possible?

Of course even if Java didn't allow access to private fields via reflection, you can always write your own runtime to do whatever you like. Or you can modify the binary .jar/.class file and change the access modifiers (I assume this is possible).

So it seems like there are three possibilities the designers of Java had to chose from:

  1. Allow direct access to private fields...maybe with a warning.
  2. Do not allow direct access to private fields, but allow access to private fields using reflection.
  3. Do not allow direct access to private fields and also do not allow access to private fields using reflection. The only way to access the private fields is to change the runtime or modify the binary .jar/.class file offline.

Choosing the middle one seems arbitrary to me...if the goal is to make it as inconvenient as possible, choice 3 is best. If the goal is to not add artificial inconvenience to things that can't be truly prevented anyway, 1 is best.

Is there something about the language or the runtime that informed or forced the decision to take choice 2?

Community
  • 1
  • 1
David Stone
  • 1,132
  • 7
  • 18
  • 2
    You can do a lot more: [How to limit setAccessible to only “legitimate” uses?](http://stackoverflow.com/questions/2481862/how-to-limit-setaccessible-to-only-legitimate-uses) – Paul Bellora Aug 14 '13 at 20:21
  • 3
    Those voting to close for "primarily opinion-based": who cares if this opinion based? Wide swaths of engineering is opinionated. Deal with it. This place would be better if we just let intelligent opinionated discussion take place. The bigger issue is that this a duplicate question. Vote to close for *that*. – jason Aug 14 '13 at 20:23
  • It is possible in C# as well (look at the answer of your link) and can be very useful for special purposes (e.g. serialization). If you do reflection, you know what you do. – slfan Aug 14 '13 at 20:24
  • 1
    In regards to Java, it is possible to disable the ability to use reflection to modify private variables by using a SecurityManager. – Jyro117 Aug 14 '13 at 20:29
  • Hi slfan, yes I know that it's possible in C# as well but in C# there is a way to enable/disable it at runtime. I didn't know if there was such a mechanism in Java, but others have answered that SecurityManager is such a mechanism. – David Stone Aug 15 '13 at 13:56
  • No big deal but I don't see how this is a duplicate of the referenced question. They both have to do with reflection and allowing access to private fields. But this question is _why_ the designers of Java chose mechanism #2 to access private fields (use reflection API) rather than allowing access to private fields another way, like adding special syntax like myobj._private_.someprivatefield. – David Stone Aug 15 '13 at 13:59

2 Answers2

2

In a sense, isn't using reflection exactly the warning you're looking for in #1?

Sometimes using reflection allows for some elegant solutions to otherwise tedious problems, how the GSON library creates and populates objects is a good example. "Normal" code shouldn't access these private fields, and using reflection lets you do so, with all the necessary overhead of exception handling and permission modification to make it clear this is not something to be done in the general case.

Reflection affords much more functionality than simply accessing private fields. It lets you, at runtime, inspect data about classes and objects you can't know at compile-time and use them to call methods and access fields that didn't exist when your code was compiled. A subset of that behavior is private access.

So yes, the Java designers could have created some sort of syntax for private access, but they also needed to create reflection, which is a more logical and powerful way to access private data; all while making it quite clear (if simply because it's complicated) that this behavior should be used with caution. To me, simply calling object.privates.field or something similar doesn't imply the same severity.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • Hi dimo414. Yes, the point I'm trying to understand is that #1 and #2 are logically equivalent. I'm wondering why the designers of Java overloaded the concept of reflection to allow for exceptional access to private fields. Rather than say add some syntax like myobject.accessprivate.privatefield. That way it would still be something that had to be done intentionally and not by default. – David Stone Aug 15 '13 at 13:54
  • Updated my answer for you. I don't think they "overloaded" the concept of reflection like you say - instead, reflection is the most logical tool to enable access to otherwise private data. – dimo414 Aug 15 '13 at 14:37
0

Sometimes you need access to private fields for unit testing. Such as testing small private functions in a class that is used internally but should not be called directly. Other times you may want to check if an internal data structure contains the correct data.

If you're using reflection as a means to access private data for other reasons you probably have to come up with a good reason to do so since most people reviewing your code (if any) will probably notice and that will come up as a red flag (the field is private for a reason right?).

Choice 2 was probably made to allow this use of reflection (which can be disabled in your non-debug builds).

Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
  • 3
    Or for serialization like JSON serialization. – Luiggi Mendoza Aug 14 '13 at 20:22
  • Thanks for the answer Jesus. I now understand better why permitting access to private fields is legitimately necessary. It still seems like the same thing could have been accomplished by adding some syntax or method on Object, like someobj.accessprivate.privatefield. That way it would still be something that had to be done explicitly and intentionally, not by accident. I think of reflection primarily as a mechanism to allow access to fields, etc, that can't be determined at compile time. It seems like they overloaded the mechanism to allow for exceptional access to private fields as well. – David Stone Aug 15 '13 at 13:52
  • 1
    Testing private methods or needing to access private fields via reflection for unit testing is a *major* smell. You should *never* to do this. The only thing that matters is the public spec. and whether or not it's satisfied. Your unit tests should be testing that. Private fields and methods are just implementation details, and testing them leads to brittle, pointless unit tests. No, no, no! – jason Aug 15 '13 at 18:59
  • @Jason Tell that to people who run code coverage and want to test cases that are VERY unlikely to happen that won't trigger unless you inject some bad data in there. – Jesus Ramos Aug 15 '13 at 19:47
  • @Jesus Ramos: Then the tools are broken. I don't know why this is so hard. Public spec. says X. Then test X. *Nothing* else matters, I don't care how likely or unlikely it is. Unless it's part of the *public* spec., it does *not* matter and is a *bad* practice to test. – jason Aug 15 '13 at 19:51
  • @Jason I know I wholeheartedly agree with you. I've made the same argument multiple times at companies that do this and they don't seem to get it. – Jesus Ramos Aug 15 '13 at 19:52
  • @Jesus Ramos: Then don't give an answer that reinforces the bad practice? :-( – jason Aug 15 '13 at 19:53
  • @Jason Been planning on rewriting my answer a little better. Just haven't sat down to do so :\ – Jesus Ramos Aug 15 '13 at 19:55