Reputation: 178
in Java it's convention (as far as I am concerned) to keep your field variables private and access them using getters and/or setters. This is so that you can set rules for changing the values of the variables.
But what if the variables are final? Example:
public class Test {
public final int MY_INT;
public Test(int myInt) {
MY_INT = myInt;
}
}
Would this be allowed? It is compiled and works fine, but is it considered good code?
Upvotes: 13
Views: 2866
Reputation: 124704
This compiles but it's not considered good code.
MY_INT
violates the naming convention: names with all caps are used for static final
variables, also known as "class constants" (see this and this, Google's Java style guide too). to conform to naming conventions, it would be better to rename to myInt
.
It's recommended to provide a getter to hide implementation details of your class. Interfaces contain only methods, not fields. If you let other classes refer to this field by name, then you lose the freedom to change the name or your internal representation later.
But most importantly, sub-classes cannot override fields, they can only override methods. If you provide a getter instead of a field, sub-classes will be able to override that and implement different behavior. So it would be better to provide a getter and forbid direct access to the field itself.
(Thanks to @Sotirios Delimanolis for the coding style guide links, much appreciated!)
Upvotes: 17
Reputation: 6178
The provider answers are incomplete (even the one selected as "the answer"). Consider what would happen if the field in question was a Collection or an array of objects. It is a good practice to make ALL fields private and provide "getters" for these fields. But more specifically, your getter should return a (immutable) reference to the field (i.e. String
), OR a defensive copy of mutable fields (i.e. array of objects). This is because, even if you cannot change the base address of the object in question, you can change the internals of the object (array or collection) by simply getting the base address. Keep in mind that by mutable fields I do not mean arrays or collections only. It applies to ANY mutable class.
Going back to the question, are getters REQUIRED? The answer is no. HOWEVER, if you want to have robust code, it is on your best interest to follow these best practices; even if it is just to create good habits. Unless you practice them regularly, you will not follow good practices when you code (and most likely others in your project won't either).
Upvotes: 6
Reputation: 6794
If the client could access the public field in your question before it had a value assigned to it (i.e., without calling the constructor), there would be an obvious issue. Specifically, this field could not have an expected/proper value when a client tried to access it. Nonetheless, as has been pointed out in the comments, you have not declared Test.MY_INT
with a static
identifier, making it essentially impossible for the value of this constant to be retrieved without first calling the constructor.
Therefore, it would appear sensible (in terms of immutability) to do what you are doing. However, in terms of "good code," you are (as others have said) forcing yourself and your clients to refer to this value explicitly by name. If you were using a getter, though, and needed to change the name of MY_INT
while keeping the purpose of the constant the same, neither you nor your client would be forced to change anything beyond the implementation in Test
.
To be more explicit, I provide your class with a getter and privatized constant.
public class Test {
private final int MY_INT;
public Test(int myInt) {
MY_INT = myInt;
}
public int getAssignedIntValue() {
return MY_INT;
}
}
I would get the assigned integer value like so:
Test test = new Test(1);
// with your class
test.MY_INT;
// with the above class
test.getAssignedIntValue();
Now, say I rename MY_INT
to myInt
to match naming conventions. In both cases, I have to change all occurrences of MY_INT
in the Test
class. But, the difference between the two implementations becomes clear when I need to get the value with the new constant name:
// if this is the old code from above
Test test = new Test(1);
// I need to change this to test.myInt, or I get an ERROR!
test.MY_INT;
// since I didn't change the name of the getter, all is well
test.getAssignedIntValue();
Note: while this may have been an acceptable answer, it does not necessarily have the most applicable reasoning. Please see this answer for reasoning given in a more general context.
Upvotes: 5
Reputation: 3108
I personally don't like public fields unless your class is just a data class. Your class is immutable but are you sure you will never want to make it mutable. If one day for some reason you need a mutable copy it is easier to have both mutable and immutable copies with getters and setters.
If you have public fields clients will use your fields in their code and you wont be able to change their names in future.
You are breaking encapsulation this way.
Upvotes: 4
Reputation: 610
Yes you can. As long as you do not initialize that variable at class level or from other setters.
Upvotes: 4