Ways to avoid passing-by-reference in Java - java

This question is probably as old as the hills. Nevertheless, after reading lots of articles and forums I still don't see a good solution to my problem.
I have to transfer some Monte Carlo simulation programs from C++ to Java. The problem is that it heavily relies on passing variables by reference in functions, like:
void make_step(int &a, int &b, double &c) {
a++;
b += a;
c *= 1.1;
}
There is no passing by reference in Java, as well as possible analogs, like multiple return values or nested functions. Solutions, which I have read on this site, usually involve encapsulation of primitive types into objects. Alternatively - break functions to single-return ones. However, in my case it results in too long and complicated code (few lines of C++ code grow to almost pages in Java). Also, since these algorithms are hard to debug, I want to avoid dramatical changes in code while porting.
What I do now is substituting of all primitive type variables with arrays of length 1 (which are objects and can be modified inside functions). But it doesn't look like very elegant solutions. Does anyone have better ideas?

If you want the parameters to be "in-out" variables, they have to be object references.
With Mutable Wrappers
You can use mutable wrappers but this will require you to slightly modify your existing code (the algorithm):
class Int {
int v;
}
class MDouble {
double v;
}
void make_step(Int a, Int b, MDouble c) {
a.v++;
b.v += a.v;
c.v *= 1.1;
}
With Local Variable Copies
If you want to keep your original code, you can create local variable copies of the wrapped parameters, and you can use those without having to modify your code.
At the end of your method (before return) copy back the local variables into the wrappers and you're done. A tip for this is to use a try-finally block so your local variables will get copied back into the wrappers no matter how or where your method returns:
void make_step(int[] aa, int[] bb, double[] cc) {
int a = aa[0];
int b = bb[0];
double c = cc[0];
try {
// all your original code comes here
a++;
b += a;
c *= 1.1;
} finally {
aa[0] = a;
bb[0] = b;
cc[0] = c;
}
}

There are few options:
Wrap all parameters in an object. The simple version indeed makes the program longer, but if you can wrap the entire algorithm in an object then those parameters become the object members.
Use mutable integers (objects) - either Java's AtomicInteger which has get()/set() methods, or the commnos-lang version

There are mutable Integer and Decimal classes out there you can use those to pass by reference. Check out Apache Commons libraries here

When writing same logic from c++ to java
Rely more on .equals and comparators over == >< for comparisions
Use member variables and for local variable return the updated objects back to the called methods to get the changes.

You can use "atomic references" to wrap your object in a reference.
There are atomicXXX classes for most basic types as well. These will work similarly to normal references aside from the overhead of creating them in the first place.
Arrays of length 1 are just as a solution, but if you dislike the syntax or appearance of them, this is the only other solution that I know of that can mimic the same behavior without a general refactor.

Related

Returning multiple primitive objects in java . Unrecommended?

I'm just beginning to learn OOP programming in java. I have already programmed a little in C++, and one of the things I miss the most in Java is the possibility to return multiple values. It's true that C++ functions only strictly return one variable, but we can use the by-reference parameters to return many more. Conversely, in Java we can't do such a thing, at least we can't for primitive types.
The solution I thought off was to create a class grouping the variables I wanted to return and return an instance of that class. For example, I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.
The thing is that I was told by someone who knows much more about Java than I know that I shouldn't create classes for the purpose of returning multiple values ( even if they are related). He told classes should never be used as C++ structs, just to group elements. He also said methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it. Which of these things are true?
I shouldn't create classes for the purpose of returning multiple values
classes should never be used as C++ structs, just to group elements.
methods shouldn't return non-primitive objects, they should receive the object from the outside and only modify it
For any of the above statements this is definitely not the case. Data objects are useful, and in fact, it is good practice to separate pure data from classes containing heavy logic.
In Java the closest thing we have to a struct is a POJO (plain old java object), commonly known as data classes in other languages. These classes are simply a grouping of data. A rule of thumb for a POJO is that it should only contain primitives, simple types (string, boxed primitives, etc) simple containers (map, array, list, etc), or other POJO classes. Basically classes which can easily be serialized.
Its common to want to pair two, three, or n objects together. Sometimes the data is significant enough to warrant an entirely new class, and in others not. In these cases programmers often use Pair or Tuple classes. Here is a quick example of a two element generic tuple.
public class Tuple2<T,U>{
private final T first;
private final U second;
public Tuple2(T first, U second) {
this.first = first;
this.second = second;
}
public T getFirst() { return first; }
public U getSecond() { return second; }
}
A class which uses a tuple as part of a method signature may look like:
public interface Container<T> {
...
public Tuple2<Boolean, Integer> search(T key);
}
A downside to creating data classes like this is that, for quality of life, we have to implement things like toString, hashCode, equals getters, setters, constructors, etc. For each different sized tuple you have to make a new class (Tuple2, Tuple3, Tuple4, etc). Creating all of these methods introduce subtle bugs into our applications. For these reasons developers will often avoid creating data classes.
Libraries like Lombok can be very helpful for overcoming these challenges. Our definition of Tuple2, with all of the methods listed above, can be written as:
#Data
public class Tuple2<T,U>{
private final T first;
private final U second;
}
This also makes it extremely easy to create custom response classes. Using the custom classes can avoid autoboxing with generics, and increase readability greatly. eg:
#Data
public class SearchResult {
private final boolean found;
private final int index;
}
...
public interface Container<T> {
...
public SearchResult search(T key);
}
methods should receive the object from the outside and only modify it
This is bad advice. It's much nicer to design data around immutability. From Effective Java 2nd Edition, p75
Immutable objects are simple. An immutable object can be in exactly one state, the state in which it was created. If you make sure that all constructors establish class invariants, then it is guaranteed that these invariants will remain true for all time, with no further effort on your part or on the part of the programmer who uses the class. Mutable objects, on the other hand, can have arbitrarily complex state spaces. If the documentation does not provide a precise description of the state transitions performed by mutator methods, it can be difficult or impossible to use a mutable class reliably.
Immutable objects are inherently thread-safe; they require no synchronization. They cannot be corrupted by multiple threads accessing them concurrently. This is far and away the easiest approach to achieving thread safety. In fact, no thread can ever observe any effect of another thread on an immutable object. Therefore, immutable objects can be shared freely.
As to your specific example ("how to return both error status and result?")
I needed to look for an object in a an array and I wanted to return a boolean(found or not) and an index. I know I could make this just setting the index to -1 if nothing was found, but I think it's more clear the other way.
Returning special invalid result values such as -1 for "not found" is indeed very common, and I agree with you that it is not too pretty.
However, returning a tuple of (statusCode, resultValue) is not the only alternative.
The most idiomatic way to report exceptions in Java is to, you guessed it, use exceptions. So return a result or if no result can be produced throw an exception (NoSuchElementException in this case). If this is appropriate depends on the application: You don't want to throw exceptions for "correct" input, it should be reserved for irregular cases.
In functional languages, they often have built-in data structures for this (such as Try, Option or Either) which essentially also do statusCode + resultValue internally, but make sure that you actually check that status code before trying to access the result value. Java now has Optional as well. If I want to go this route, I'd pull in these wrapper types from a library and not make up my own ad-hoc "structs" (because that would only confuse people).
"methods shouldn't return non-primitive objects , they should receive the object from the outside and only modify it"
That may be very traditional OOP thinking, but even within OOP the use of immutable data absolutely has its value (the only sane way to do thread-safe programming in my book), so the guideline to modify stuff in-place is pretty terrible. If something is considered a "data object" (as opposed to "an entity") you should prefer to return modified copies instead of mutating the input.
For some static Information you can use the static final options. Variables, declared as static final, can be accessed from everywhere.
Otherwise it is usual and good practise to use the getter/ setter concept to receive and set parameters in your classes.
Strictly speaking, it is a language limitation that Java does not natively support tuples as return values (see related discussion here). This was done to keep the language cleaner. However, the same decision was made in most other languages. Of course, this was done keeping in mind that, in case of necessity, such a behaviour can be implemented by available means. So here are the options (all of them except the second one allow to combine arbitrary types of return components, not necessarily primitive):
Use classes (usually static, self-made or predefined) specifically designed to contain a group of related values being returned. This option is well covered in other answers.
Combine, if possible, two or more primitive values into one return value. Two ints can be combined into a single long, four bytes can be combined into a single int, boolean and unsigned int less than Integer.MAX_VALUE can be combined into a signed int (look, for example, at how Arrays.binarySearch(...) methods return their results), positive double and boolean can be combined into a single signed double, etc. On return, extract the components via comparisons (if boolean is among them) and bit operations (for shifted integer components).
2a. One particular case worth noting separately. It is common (and widely used) convention to return null to indicate that, in fact, the returned value is invalid. Strictly speaking, this convention substitutes two-field result - one implicit boolean field that you're using when checking
if (returnValue != null)
and the other non-primitive field (which can be just a wrapper of a primitive field) containing the result itself. You use it after the above checking:
ResultClass result = returnValue;
If you don't want to mess with data classes, you can always return an array of Objects:
public Object[] returnTuple() {
return new Object[]{1234, "Text", true};
}
and then typecast its components to desired types:
public void useTuple() {
Object[] t = returnTuple();
int x = (int)t[0];
String s = (String)t[1];
boolean b = (boolean)t[2];
System.out.println(x + ", " + s + ", " + b);
}
You can introduce field(s) into your class to hold auxiliary return component(s) and return only the main component explicitly (you decide which one is the main component):
public class LastResultAware {
public static boolean found;
public static int errorCode;
public static int findLetter(String src, char letter) {
int i = src.toLowerCase().indexOf(Character.toLowerCase(letter));
found = i >= 0;
return i;
}
public static int findUniqueLetter(String src, char letter) {
src = src.toLowerCase();
letter = Character.toLowerCase(letter);
int i = src.indexOf(letter);
if (i < 0)
errorCode = -1; // not found
else {
int j = src.indexOf(letter, i + 1);
if (j >= 0)
errorCode = -2; // ambiguous result
else
errorCode = 0; // success
}
return i;
}
public static void main(String[] args) {
int charIndex = findLetter("ABC", 'b');
if (found)
System.out.println("Letter is at position " + charIndex);
charIndex = findUniqueLetter("aBCbD", 'b');
if (errorCode == 0)
System.out.println("Letter is only at position " + charIndex);
}
}
Note that in some cases it is better to throw an exception indicating an error than to return an error code which the caller may just forget to check.
Depending on usage, this return-extending fields may be either static or instance. When static, they can even be used by multiple classes to serve a common purpose and avoid unnecessary field creation. For example, one public static int errorCode may be enough. Be warned, however, that this approach is not thread-safe.

What is the difference between the return function and storing a variable?

I'm learning how to code in Java. I'm a little confused by "return;" and what it does and when we use it. Please see the following example of code:
public int something() {
return 1;
}
public static void main() {
int returnValue = something();
System.out.println(returnValue);
//Prints 1
}
Why wouldn't we just store 1 into a int variable called something then use System.out.print(something);
When would we use the return method instead of simply storing into a variable?
Thank you
Sure you could store into a variable but then you would lose one of the very important features, namely the ability to call the method inside itself.
This is relevant for algorithms that divide the work into smaller chunks and invoke themselves on the smaller chunks (and then combine the individual result to a big result). This is very common in sorting algorithms. The technical term is recursion.
Usually the compiler actually does exactly this; creates a variable for storing the value from where the calling code can pick it up. This variable is typically put in the same location - the stack - as the parameters passed in to the called method, and is invisible to your code.
(Also it is needed to make it threadsafe which is essential to utilizing more than one core on a modern cpu).

Iterating and counting across class variables in Java

I have class, which contains variables of multiple type, most of those (about 30) are double:
String something;
double x;
double y;
double z;
...
I want to iterate over doubles, but also keep them written in this "classic way", not inside array, because derived classes use most of them. The function I am having problem with now is how to iterate across all the double type variables, find how many of those are non zero and then pick one of all these variables randomly. There will be thousands of instances of this class and as I said, there are classes that expand this one. So I am working on solution, preferably something like pseudo:
nonzeros = 0
foreach doubleVarInClass variable
{
if (variable != 0)
nonzeros++;
}
if (nonzeros < parameter)
{
randomDoubleVarInClass = random.next(...);
}
One solution which I was thinking about was to use HashMap to keep all the variables in, but then I will have to rewrite all classes that uses this one and not sure how it will affect performance, since it will be pretty intensively used all the time. Should I be afraid of performance and try something with classic arrays perhaps? I'd like to atleast keep variable names if nothing. I thought about array with references to these variables, so I can keep them written this way, not sure if its possible due to value passing in Java.
Also maybe there is some structure that keeps info about how many of those are non zero or have efficient function for it?
Thank you for any info that could solve my problem :)
I suggest using reflection for this. Suppose you have instance of your class named o:
int nonzeros = 0;
for (Field f : o.getClass().getDeclaredFields()) {
f.setAccessible(true);
if (f.getType().equals(Double.TYPE) && f.getDouble(o) != 0.0) {
nonzeros++;
}
}
NOTE: Java Reflection will probably be bad idea from the point of performance, and you should test this first, from that point of view. Besides that, this provide easy checks without any changes in your class definition. In Java 6 performance of reflection is little better than on older versions, and you should check this in your personal use case and in your environment.

set/get methods in C++

Java programmers and API seems to favor explicit set/get methods.
however I got the impression C++ community frowns upon such practice.
If it is so,is there a particular reason (besides more lines of code) why this is so?
on the other hand, why does Java community choose to use methods rather than direct access?
Thank you
A well designed class should ideally not have too many gets and sets. In my opinion, too many gets and sets are basically an indication of the fact that someone else (and potentially many of them) need my data to achieve their purpose. In that case, why does that data belong to me in the first place? This violates the basic principle of encapsulation (data + operations in one logical unit).
So, while there is no technical restriction and (in fact abundance of) 'set' and 'get' methods, I would say that you should pause and reinspect your design if you want too many of those 'get' and 'set' in your class interface used by too many other entities in your system.
There are occasions when getters/setters are appropriate but an abundance of getters/setters typically indicate that your design fails to achieve any higher level of abstraction.
Typically it's better (in regards to encapsulation) to exhibit higher level operations for your objects that does not make the implementation obvious to the user.
Some other possible reasons why it's not as common in C++ as in Java:
The Standard Library does not use it.
Bjarne Stroustrup expresses his dislike towards it (last paragraph):
I particularly dislike classes with a
lot of get and set functions. That is
often an indication that it shouldn't
have been a class in the first place.
It's just a data structure. And if it
really is a data structure, make it a
data structure.
The usual argument against get/set methods is that if you have both and they're just trivial return x; and x = y; then you haven't actually encapsulated anything at all; you may as well just make the member public which saves a whole lot of boilerplate code.
Obviously there are cases where they still make sense; if you need to do something special in them, or you need to use inheritance or, particularly, interfaces.
There is the advantage that if you implement getters/setters you can change their implementation later without having to alter code that uses them. I suppose the frowning on it you refer to is kind of a YAGNI thing that if there's no expectation of ever altering the functions that way, then there's little benefit to having them. In many cases you can just deal with the case of altering the implementation later anyway.
I wasn't aware that the C++ community frowned on them any more or less than the Java community; my impression is that they're rather less common in languages like Python, for example.
I think the reason the C++ community frowns on getters and setters is that C++ offers far better alternatives. For example:
template <class T>
class DefaultPredicate
{
public:
static bool CheckSetter (T value)
{
return true;
}
static void CheckGetter (T value)
{
}
};
template <class T, class Predicate = DefaultPredicate <T>>
class Property
{
public:
operator T ()
{
Predicate::CheckGetter (m_storage);
return m_storage;
}
Property <T, Predicate> &operator = (T rhs)
{
if (Predicate::CheckSetter (rhs))
{
m_storage = rhs;
}
return *this;
}
private:
T m_storage;
};
which can then be used like this:
class Test
{
public:
Property <int> TestData;
Property <int> MoreTestData;
};
int main ()
{
Test
test;
test.TestData = 42;
test.MoreTestData = 24;
int value = test.TestData;
bool check = test.TestData == test.MoreTestData;
}
Notice that I added a predicate parameter to the property class. With this, we can get creative, for example, a property to hold an integer colour channel value:
class NoErrorHandler
{
public:
static void SignalError (const char *const error)
{
}
};
class LogError
{
public:
static void SignalError (const char *const error)
{
std::cout << error << std::endl;
}
};
class Exception
{
public:
Exception (const char *const message) :
m_message (message)
{
}
operator const char *const ()
{
return m_message;
}
private:
const char
*const m_message;
};
class ThrowError
{
public:
static void SignalError (const char *const error)
{
throw new Exception (error);
}
};
template <class ErrorHandler = NoErrorHandler>
class RGBValuePredicate : public DefaultPredicate <int>
{
public:
static bool CheckSetter (int rhs)
{
bool
setter_ok = true;
if (rhs < 0 || rhs > 255)
{
ErrorHandler::SignalError ("RGB value out of range.");
setter_ok = false;
}
return setter_ok;
}
};
and it can be used like this:
class Test
{
public:
Property <int, RGBValuePredicate <> > RGBValue1;
Property <int, RGBValuePredicate <LogError> > RGBValue2;
Property <int, RGBValuePredicate <ThrowError> > RGBValue3;
};
int main ()
{
Test
test;
try
{
test.RGBValue1 = 4;
test.RGBValue2 = 5;
test.RGBValue3 = 6;
test.RGBValue1 = 400;
test.RGBValue2 = 500;
test.RGBValue3 = -6;
}
catch (Exception *error)
{
std::cout << "Exception: " << *error << std::endl;
}
}
Notice that I made the handling of bad values a template parameter as well.
Using this as a starting point, it can be extended in many different ways.
For example, allow the storage of the property to be different to the public type of the value - so the RGBValue above could use an unsigned char for storage but an int interface.
Another example is to change the predicate so that it can alter the setter value. In the RGBValue above this could be used to clamp values to the range 0 to 255 rather than generate an error.
Properties as a general language concept technically predate C++, e.g. in Smalltalk, but they weren't ever part of the standard. Getters and setters were a concept used in C++ when it was used for development of UI's, but truth be told, it's an expensive proposition to develop UI's in what is effectively a systems language. The general problem with getters and setters in C++ was that, since they weren't a standard, everybody had a different standard.
And in systems languages, where efficiency concerns are high, then it's just easier to make the variable itself public, although there's a lot of literature that frowns mightily on that practice. Often, you simply see richer exchanges of information between C++ object instances than simple items.
You'll probably get a lot of viewpoints in response to this question, but in general, C++ was meant to be C that did objects, making OOP accessable to developers that didn't know objects. It was hard enough to get virtuals and templates into the language, and I think that it's been kind of stagnant for a while.
Java differs because in the beginning, with what Java brought in areas like garbage collection, it was easier to promote the philosophy of robust encapsulation, i.e. external entities should keep their grubby little paws off of internal elements of a class.
I admit this is pretty much opinion - at this time I use C++ for highly optimized stuff like 3D graphics pipelines - I already have to manage all my object memory, so I'd take a dim view of fundamentally useless code that just serves to wrap storage access up in additional functions - that said, the basic performance capabilies of runtimes like the MSFT .net ILM make that a position that can be difficult to defend at times
Purely my 2c
There's nothing unusual about having explicit set/get methods in C++. I've seen it in plenty of C++, it can be very useful to not allow direct access to data members.
Check out this question for an explanation of why Java tends to prefer them and the reasons for C++ are the same. In short: it allows you to change the way data members are accessed without forcing client code (code that uses your code) to recompile. It also allows you to enforce a specific policy for how to access data and what to do when that data is accessed.
By mandating the use of set/get methods, one can implement useful side-effects in the getter/setter (for example, when the argument to get/set is an object).
I am surprised nobody has mentioned Java introspection and beans yet.
Using get.../set... naming convention combined with introspection allows all sorts of clever trickery with utility classes.
I personally feel that the "public" keyword should have been enough to trigger the bean magic but I am not Ray Gosling.
My take on this is that in C++ is a rather pointless exercise. You are adding at least six lines of code to test and maintain which perform no purpose and will for the most part be ignored by the compiler. It doesnt really protect your class from misuse and abuse unless you add a lot more coding.
I don't think the C++ community frowned on using getters and setters. They are almost always a good idea.
It has to do with the basics of object oriented programming - hiding the internals of an object from its users. The users of an object should not need to know (nor should they care) about the internals of an object.
It also gives you control over what is done whenever a user of your object tries to read/write to it. In effect, you expose an interface to the object's users. They have to use that interface and you control what happens when methods in that interface are called - the getters and setters would be part of the interface.
It just makes things easier when debugging. A typical scenario is when your object lands up in a weird state and you're debugging to find out how it got there. All you do is set breakpoints in your getters and setters and assuming all else is fine, you're able to see how your object gets to the weird state. If your object's users are all directly accessing its members, figuring out when your object's state changes becomes a lot harder (though not impossible)
I would argue that C++ needs getters/setters more than Java.
In Java, if you start with naked field access, and later you changed your mind, you want getter/setter instead, it is extremely easy to find all the usages of the field, and refactor them into getter/setter.
in C++, this is not that easy. The language is too complex, IDEs simply can't reliably do that.
so In C++, you better get it right the first time. In Java, you can be more adventurous.
There were gets/sets long before java. There are many reasons to use them, especially, if you have to recalculate sth. wenn a value changes. So the first big advantage is, that you can watch to value changes. But imho its bad to ALWAYS implement get and set-often a get is enough. Another point is, that class changes will directly affect your customers. You cant change member names without forcing to refactor the clients code with public members. Lets say, you have an object with a lenght and you change this member name...uh. With a getter, you just change you side of the code and the client can sleep well. Adding gets/Sets for members that should be hidden is of course nonsense.

Premature optimization in Java: when to use "x = foo.getX()" vs simply "foo.getX()"

When I find myself calling the same getter method multiple times, should this be considered a problem? Is it better to [always] assign to a local variable and call only once?
I'm sure the answer of course is "it depends".
I'm more concerned about the simpler case where the getter is simply a "pass-along-the-value-of-a-private-variable" type method. i.e. there's no expensive computation involved, no database connections being consumed, etc.
My question of "is it better" pertains to both code readability (style) and also performance. i.e. is it that much of a performance hit to have:
SomeMethod1(a, b, foo.getX(), c);
SomeMethod2(b, foo.getX(), c);
SomeMethod3(foo.getX());
vs:
X x = foo.getX();
SomeMethod1(a, b, x, c);
SomeMethod2(b, x, c);
SomeMethod3(x);
I realize this question is a bit nit-picky and gray. But I just realized, I have no consistent way of evaluating these trade-offs, at all. Am fishing for some criteria that are more than just completely whimsical.
Thanks.
The choice shouldn't really be about performance hit but about code readability.
When you create a variable you can give it the name it deserves in the current context. When you use a same value more than one time it has surely a real meaning, more than a method name (or worse a chain of methods).
And it's really better to read:
String username = user.getName();
SomeMethod1(a, b, username, c);
SomeMethod2(b, username, c);
SomeMethod3(username);
than
SomeMethod1(a, b, user.getName(), c);
SomeMethod2(b, user.getName(), c);
SomeMethod3(user.getName());
For plain getters - those that just returns a value - HotSpot inlines it in the calling code, so it will be as fast as it can be.
I, however, have a principle about keeping a statement on a single line, which very often results in expressions like "foo.getBar()" being too long to fit. Then it is more readable - to me - to extract it to a local variable ("Bar bar = foo.getBar()").
They could be 2 different things.
If GetX is non-deterministic then the 1st one will give different results than the 2nd
Personally, I'd use the 2nd one. It's more obvious and less unnecessarily verbose.
I use the second style if it makes my code more readable or if I have to use the assigned value again. I never consider performance (on trivial things) unless I have to.
That depends on what getX() actually does. Consider this class:
public class Foo {
private X x;
public X getX() { return x; }
}
In this case, when you make a call to foo.getX(), JVM will optimize it all the way down to foo.x (as in direct reference to foo's private field, basically a memory pointer). However, if the class looks like this:
public class Foo {
private X x;
public X getX() { return cleanUpValue(x); }
private X cleanUpValue(X x) {
/* some modifications/sanitization to x such as null safety checks */
}
}
the JVM can't actually inline it as efficiently anymore since by Foo's constructional contract, it has to sanitize x before handing it out.
To summarize, if getX() doesn't really do anything beyond returning a field, then there's no difference after initial optimization runs to the bytecode in whether you call the method just once or multiple times.
Most of the time I would use getX if it was only once, and create a var for it for all other cases. Often just to save typing.
With regards to performance, the compiler would probably be able to optimize away most of the overhead, but the possibility of side-effects could force the compiler into more work when doing multiple method-calls.
I generally store it locally if:
I'm will use it in a loop and I don't want or expect the value to change during the loop.
I'm about to use it in a long line of code or the function & parameters are very long.
I want to rename the variable to better correspond to the task at hand.
Testing indicates a significant performance boost.
Otherwise I like the ability to get current values and lower level of abstraction of method calls.
Two things have to be considered:
Does the call to getX() have any side effects? Following established coding patterns, a getter should not alter the object on which it is called, the in most cases, there is no side effect. Therefore, it is semantically equivalent to call the getter once and store the value locally vs. calling the getter multiple times. (This concept is called idempotency - it does not matter whether you call a method once or multiple times; the effect on the data is exactly the same.)
If the getter has no side effect, the compiler can safely remove subsequent calls to the getter and create the temporary local storage on its own - thus, the code remains ultra-readable and you have all the speed advantage from calling the getter only once. This is all the more important if the getter does not simply return a value but has to fetch/compute the value or runs some validations.
Assuming your getter does not change the object on which it operates it is probably more readable to have multiple calls to getX() - and thanks to the compiler you do not have to trade performance for readability and maintainability.

Categories