2

Once upon a time:

I had a classA which had many fields. I injected class A to classB and class C through their constructors because the last two needed to communicate with classA.

Problem:

So I have done the dependency injection and now I noticed that class B and class C were sad because they couldnt access the fields from class A which were set to private. They tried it through getters but class A quickly became too fat and so both classes wondered if there was a way to access the fields of their dependency without getters and without setting them to public.

Example (Pseudo code!!!):

class A {
 private field1 = 1;
 private field2 = 2;
 private field3 = 3;
 private field4 = 4;
 private field5 = 5;
 private field6 = 6;
}

class B {
    public B(A a) {
      System.out.print(a.field1);
    }
}

class C {
    public B(A a) {
      System.out.print(a.field2);
    }
}

A a = new A();

new B(a);
new C(a);

Inheritance and setting fields to protected would solve things but the problem is each child would have a different parent. I dont want that.

So my question is: How can I access the fields of a dependency without getters or reflection?

Asperger
  • 3,064
  • 8
  • 52
  • 100
  • Second of all, `private` means private, which means a private field can only be accessed within it's class, which means you'd have to create a `method` of more open restrictions in order to access it from outside, which means a `Getter`... --- Well, you ***could*** do it with reflection, by setting to accessible temporarily...But that'd be very ***wrong*** if your objective is "to not bloat the class"... – CosmicGiant Oct 01 '16 at 14:32
  • @AndrewL. I know its invalid java. Main is missing so what? The private data cant be read either...I know. Read the whole thing xD. – Asperger Oct 01 '16 at 14:32
  • @Tom the other idea I had was setting the fields to "final and public" but that would make them immutable – Asperger Oct 01 '16 at 14:33
  • Getters are verbose and a bit noisy, but they're not what makes a class fat. Either your class is really too fat, and you should reconsider its design and try to split it into multiple classes, or you just don't like getters, and should thus accept them, or choose another language like Kotlin, which makes their syntax much less verbose. – JB Nizet Oct 01 '16 at 14:33
  • 1
    @Tom You're right, sorry about that – Andrew Li Oct 01 '16 at 14:36
  • @Asperger consider using [Lombok](https://projectlombok.org/), it can generate getters for you, and you won't need to obfuscate your code with them anymore (: – Jezor Oct 01 '16 at 14:39
  • @Jezor nice one : ) – Asperger Oct 01 '16 at 14:43
  • @Jezor Wait... Why would you use an extension for this? Pretty much all (good) IDEs like NetBeans, Eclipse and IntelliJIdea already support auto-generation of getters, setters and more... Just google for your IDE's shortcut for it and live happily ever after... – CosmicGiant Oct 01 '16 at 14:48
  • 1
    @AlmightyR because it's generated by annotations (so at compile time) // and as a side note there are other interesting features, not just getters/setters –  Oct 01 '16 at 14:50
  • @RC. You can easily set IDEs to do this in less than 5 minutes... I still don't see the point of *bloating* (pah-dum-pshh) your development environment with this... – CosmicGiant Oct 01 '16 at 14:52
  • Then don't use it.. –  Oct 01 '16 at 14:57
  • @RC. still what about setting public final on fields that stay immutable? – Asperger Oct 01 '16 at 15:00
  • @Asperger `public final` means that a field is `immutable`, setting it is prohibited by definition... yes, you can do it (reflection), but it doesn't mean you **should**. – Jezor Oct 01 '16 at 15:39
  • @AlmightyR I believe that boilerplate code slows down development, and if you don't like using additional dependency (I see nothing wrong with that, though), you can always [delombok](https://projectlombok.org/features/delombok.html) your code afterwards. – Jezor Oct 01 '16 at 15:47
  • @Jezor Wait wait wait... Unless lombok automatically create getters for all fields (even ones that shouldn't have getters... = very bad), or uses dark magic (very worse), you have to type something or trigger a shortcut to inject the code (in this case annots) anyways... Why is pressing the shortcut-keys for the IDE's own auto-generation (which can also be made into annots) considered "boilerplate that slows development", but ***doing the same thing or worse*** on lombok is (supposedly) faster or non-boilerplate? "o_0 – CosmicGiant Oct 01 '16 at 16:04
  • @AlmightyR makes sense lol – Asperger Oct 01 '16 at 16:18
  • @AlmightyR IDEs can auto-generate accessors / mutators based on annotations? – Jezor Oct 01 '16 at 16:19
  • @AlmightyR you can use lombok's `@Getter` and `@Setter` annotations on fields (therefore excluding fields that are not meant to be accessed from the outside of a class), but let's face it, if your class requires them it's either DTO, or bad design. – Jezor Oct 01 '16 at 16:22
  • @Jezor Sure can! Well, at least in NetBeans, you can configure both, custom annotations, and the auto-generated code... So all you'd need to do is setup a custom annotation to generate getters, and then replace the standard auto-generation template code with one that contains the annotation. =) --- I haven't done that myself because I don't mind the getter/setter code (if/when it gets annoying, I just `"fcom"+tab` it into a collapsible comment-tittled section...<3 this in NetBeans BTW!), but I have college friends who have, and it's quite easy to setup (just need google and about 5 mins) – CosmicGiant Oct 01 '16 at 16:42
  • @AlmightyR sounds interesting, but lombok will work everywhere and won't require your team to use specific IDE. Also, it's more than just getters / setters generator. I'm developing webapps in Spring and things like `@AllArgsConstructor(onConstructor = @__(@Autowired))` make my work a lot more enjoyable. – Jezor Oct 01 '16 at 18:01
  • @Jezor AFAIK all main java IDEs (NetBeans, Eclipse, InltelliJ IDEA, etc...) have this kind of feature and it's easy enough to implement... I only mentioned NetBeans specifically because that's the one I use. --- Also, in the context of what the OP specified here, it ***is*** just getters/setters... IMO, one should leave getting more stuff to when that's actually needed, otherwise it's just bloating your dev-env, as mentioned earlier. =) – CosmicGiant Oct 01 '16 at 20:00

1 Answers1

5

The only way to access to private fields is with the Reflection API as next:

Field field1 = A.class.getDeclaredField("field1");
// Make it accessible as it is a private field otherwise you won't be able to get the value
field1.setAccessible(true);
MyClass obj = (MyClass) field1.get(a);

However using Reflection API should be your last resort as it is more a hack in this case than a real solution.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
  • Was [this](http://stackoverflow.com/questions/1196192/how-do-i-read-a-private-field-in-java) the source? If it was, please credit! =) – CosmicGiant Oct 01 '16 at 14:38
  • I heared about reflection being evil. In this context would it be or is it a proper sane use? The other idea I had was: "public final" but that would make things immutable. – Asperger Oct 01 '16 at 14:39
  • @Asperger, if your objective is to "avoid code bloating", as you described in the OP, then reflection in this case would be far more than just *evil*... It would be like... The king of the underworld... xP – CosmicGiant Oct 01 '16 at 14:41
  • 1
    @Asperger no, it's reflection is definitely not a good idea just to get rid of getters. Accept they're needed, or refactor your class into several ones, or use Lombok to auto-generate them, or use another language which has support for properties without the verbosity of Java, or combine several of these solutions. – JB Nizet Oct 01 '16 at 14:41
  • @AlmightyR of course not, I use Reflection API for many years, I don't need it to implement that – Nicolas Filotto Oct 01 '16 at 14:41
  • 1
    @NicolasFilotto Oh, ok then... Thought it might have been inspired, since the code is basically identical... But then again, there aren't many other ways to do it, so I wanted to make sure... =P --- PS: +1 now that you've clarified that reflection would be inappropriate in this case. =) – CosmicGiant Oct 01 '16 at 14:43
  • Damn, how I miss javascripts prototyping – Asperger Oct 01 '16 at 14:47