Java language convention; getters / setters
Public class Example {
private int number;
public Example(int number){
this.number = number;
}
public int getNumber(){
return number;
}
public void setNumber(int number){
this.number = number;
}
public static void main(String[] args){
Example e = new Example(5);
What is offered when accessing a variable within its class; "e.number" or "e.getNumber ()"?
Edit :
I think the most important question is whether the compiler knows the method you are calling a getter or a setter. So e.setNumber(5);
will be as fast ase.number = 5;
a source to share
I would say it depends on the situation. If the field is going to be something simple, like int
and that is unlikely to change in the future , I access it using number
, not getNumber()
.
If the field represents something more active, which in some situations can be computed in a future situation, or possibly overridden in a subclass , it getNumber()
is an obvious choice.
My rule of thumb: If there is any distant opportunity that I can learn from using getNumber()
, I use getNumber()
, otherwise I use number
for clarity and brevity.
a source to share
this.number
Most of the time they will be optimized for the same code, but the point of using setters / getters is to avoid changing the API if the implementation changes. However, in the class you are not using the "API", but you see all the internals and state.
Alternatively, you can use
numer += 5;
instead
setNumber(getNumber() + 5);
Edit . Outside the class, of course, it will be protected with a getter / setter as you can change the internal representation and you can ensure backward compatibility by overriding them in terms of the new state representation.
Edit 2 : a main
little bit special. I would say it main
should be as minimal as possible - create some objects and call one or two methods at most - hence it shouldn't assign variebles and should be treated as an "external" part. On the other hand, some of them provide test methods in main
which may require direct access to state. Therefore, if you may not have direct access to fields in main
.
main
It doesn't matter in terms of speed , since starting the JVM would compensate for any overhead. The real difference would be in the inner loops in which the JIT takes care of this.
a source to share
It will only make a difference if the getter / setter does something extra. If you know from the beginning it will be like this, then use methods even inside the class. If it wasn't for me, I would just go with direct field manipulation and rely on Eclipse to help me refactor later if needed.
a source to share
To answer your last question, take a look at this example,
Java code:
public void test2() {
setNumber(getNumber() + 1);
}
Bytecode:
public test2()V
L0
LINENUMBER 47 L0
ALOAD 0
ALOAD 0
INVOKEVIRTUAL com/test/ByteCodeTester.getNumber()I
ICONST_1
IADD
INVOKEVIRTUAL com/test/ByteCodeTester.setNumber(I)V
L1
LINENUMBER 48 L1
RETURN
L2
LOCALVARIABLE this Lcom/test/ByteCodeTester; L0 L2 0
MAXSTACK = 3
MAXLOCALS = 1
As you can see, the bytecode still makes 2 method calls. Therefore, the compiler does not treat it differently in this case.
a source to share
If a public accessor exists for a different purpose, it is preferable to use that accessor because you will ensure consistent access to your variable.
However, if your variable does not have public access, it is considered acceptable to access the variable directly. I tend to restrict private variables (i.e. no private helpers in the code, but protected accessors instead of protected members if you need access in the base class implementation).
So, to summarize: I've always kept members private and accessed via accessors, except when only the necessary accessors are needed.
a source to share
I generally prefer to still go through the setters / getters even when you visit the class internally.
I do this because there might be times when I want to change the getters to do more than just retrieve a property (like a lazy load variable), and I want the flexibility to be able to do this without having to worry about changing other parts class.
However, there are exceptions, although they are mostly more personal preference than general best practice. I will access member variables directly:
- When the realization of what I consider the functionality of "low level" (and this is entirely subjective, in my case, I consider
#equals()
,#hashCode()
,#toString()
and the like "low level"). I don't think there is a very strong technical reason for this, it just "feels" better for me. - If it's too hard to use setters / getters (e.g.
num ++
vssetNumber(getNumber() + 1
) as someone else pointed out). - Unless my recipient is doing some extra work and in my particular case, I don't want this behavior.
- ... And there are probably other cases that I missed ...
a source to share
say goodbye to multithreading with this.number = .. not to mention the possible need to implement control over what might be inside this.number. With setNumber (), Java concludes that this method can be final and can do a lot with optimizations, so you can't really feel the difference ...
a source to share
The great thing about getters / setters is that they can often do a little more than act as an interface to a private field. The return value of / set can be part of a more complex computation that happens behind the scenes.
However, the danger is that since they are full method calls, they can literally do anything - start a process, download a file, perform an expensive task, etc. This is, of course, silly from a getter / setter context, but it is something that can be avoided. I've also heard of code that does most of what it wanted to do in getters / setters without having real methods!
a source to share
The JVM will optimize the call to the setter method when it is safe to do so (i.e., almost anyway, when you are tempted to just use this field). So for performance, it doesn't matter unless you are running on a JVM that doesn't JIT compilation (like Dalvik). In fact, you can intercept method calls at many levels, and the JVM will optimize it for accessing the field when it actually runs it on hardware.
This way you don't have to worry about the performance overhead associated with getters / setters at all, unless they really do something extra (which isn't here). Instead, you can make a decision based on other criteria (do you want the flexibility to change the underlying view? Would you like to override it in later classes, and if so, is this the correct override / getter, or is this the correct field access? And etc.).
a source to share