Given the following two code options, is there any performance benefit (over a very large scale or a long period of time) of the second over the first?
Option 1
private Map<Long, Animal> animals = ...;
public Map<Long, Animal> getAnimals() {
return animals;
}
public void useAnimals() {
for (int i=0; i < SOME_LARGE_NUMBER; i++) {
Animal animal = getAnimals().get(id);
}
// Many many calls to getAnimals() are made...
}
Option 2 – no getter
private Map<Long, Animal> animals = ...;
public void useAnimals() {
for (int i=0; i < SOME_NUMBER; i++) {
Animal animal = animals.get(id);
}
// No method calls made
}
If it is bad for performance, why, and how should I determine whether it is worth mitigating?
And, would storing the result of getAnimals() as a local provide a benefit…
- if
SOME_NUMBERis hundreds or thousands? - if
SOME_NUMBERis only in the order of magnitude of 10?
Note: I previously said “encapsulation”. I changed it to “getter” because the purpose is actually not that the field can’t be modified but that it can’t be reassigned. The encapsulation is simply to remove responsibility for assignment from subclasses.
Most likely JVM will inline
getAnimals()invocation in tight loop effectively falling back to Option 1. So don’t bother, this is really a micro (nano?) optimization.Another thing is migrating from field access to local variable. This sounds good since instead of traversing through
thisreference every time you always have a reference on the stack (two memory accesses vs. one). However I believe (correct me if I’m wrong) that sinceanimalsis private and non-volatileagain JVM will perform this optimization for you at runtime.