Background:
When you extract methods out of long code pieces, you often run into the call-by-value problem with primitive variables. You cannot change those primitive parameters in the extracted method so that the caller sees the changes. You can avoid that by making the primitive variable an array with only one element. Then it is effectively used call-by-reference. However it is now an object on the heap. Is the escape analysis of Java clever enough to understand that and use the stack despite that?
Given following code and the case it could not be inlined:
public class EscapeAnalysisTest {
public static void main(String[] args) {
final Set<Integer> integers = new HashSet<>();
integers.add(1);
integers.add(9);
integers.add(8);
integers.add(4);
// and so on ...
final long[] product = new long[1];
final long[] sum = new long[1];
final long[] count = new long[1];
final int[] max = new int[1];
final int[] min = new int[1];
product[0] = 1L;
max[0] = Integer.MIN_VALUE;
min[0] = Integer.MAX_VALUE;
for (Integer i : integers) {
calcSomeValues(product, sum, count, max, min, i);
}
System.out.println("Product :" + product[0]);
System.out.println("Sum :" + sum[0]);
System.out.println("Count:" + count[0]);
System.out.println("Max:" + max[0]);
System.out.println("Min:" + min[0]);
}
private static void calcSomeValues(final long[] product, final long[] sum, final long[] count, final int[] max,
final int[] min, Integer i) {
product[0] *= i;
sum[0] += i;
count[0]++;
max[0] = Math.max(max[0], i);
min[0] = Math.min(min[0], i);
}
}
Here's a better way to do this:
Using arrays the way you have is just weird. Don't do it. This will confuse other programmers and isn't how the language is intended to be used. It violates the Principle of Least Astonishment.
Instead, find a way to make the system work for you without going into weird territory. You have multiple values that are logically associated with each other, and they're all computed at the same time. When you have several values that are used together, it's a good time to think about using a class. By using a class and a single method that does all the updating, your code is clear and sensible. The class I've provided actually ends up being immutable (as far as external code is concerned) because the logic of computing the summary is all inside the
summarize
method, which has access to the private attributes, so it's very well encapsulated. (The names could probably be better, but I think this is good enough as an example.) If modifying the private state insummarize
is undesirable, this can be easily adapted by givingSummary
arguments with the values of its instance variables and simply passing the values into the constructor after computing them as local variables, which would turnSummary
into a very simple result object.Keeping all this logic very localized and preventing callers from modifying the result makes it very easy to reason about what's going on. Your example code with length one arrays violates both of those principles and makes it harder to understand, use, or maintain the code.
Alternately, if you can use the values immediately after calculating them, you can skip the class and just calculate them all in line. You could do this via a loop or calculate them separately using built in functionality.