Search code examples
javaimmutabilityprivatepublicaccessor

Should an immutable class member have an accessor method or allowed to be public?


I have a question about best design practices. I have been attempting to build more immutable components into my project because I read they were easier to maintain in the long run and wanted to test this.

When you have a class with immutable data members, say

 public/private final int importantNumber = 3;

Should the int still be declared as private and given an accessor method, or because its finals, what is the hard in allowing direct access and making it public? I don't see any issues with it being made public because you are unable to change it.

In my case, the immutable object is created with values that are passed into it and then will self populate the others from a database, with everything being final.

Or is this merely a question of preference and will spark a religious war? As there are lots of questions about accessing the data member from inside the class, I want to make it clear that I am asking from another external class attempting to get the value.


Solution

  • Making things public allows other code to rely on it.

    It doesn't matter if the data is mutable or immutable. As soon as some other code makes itself dependant on that information, you enable future problems. And in any larger project, these problems will manifest themselves sooner or later.

    Making things public, all of a sudden, (internal) implementation details can leak into other code! And of course: if that data is mutable, that just opens a real can of worms.

    But even a simple if (someObject.someField == whatever) then do this else do that can quickly turn into a huge problem. Just assume you have that code in 10, 50, 100 different places in your huge project.

    Thus, your default rule is: hide your information. Making things public is the exception, it happens because you absolutely want your design to be that way. Your default is to give your fields (and even methods) the most restrictive visibility that still allows you to implement your requirements.

    And note: it is just "slightly" better to hide the field and having an accessor method for it. Because if (someObject.someMethod() == ...) leads to the same problems. And (almost) worse: now you decide that someMethod() should do something different, to solve one specific problem. But are you sure that the other 99 usages of that method call work fine with that change?!

    Final caveat: Java 9 introduced the module concept, so you are now finally able to have something public, but still not usable from outside your module. But that is more of a theoretical addendum, I would still go with the base rule and make not things public unless I have good reasons to do so. If you want to access that information, say for unit tests, then a package protected getter should do.