Why java.util.Map value can increment primitive array but not single Integer

Here are three examples:

Example 1:

int j[] = new int[]{2,2,2,2};
HashMap<Integer, int[]> m = new HashMap<>();
m.put(5,j);
m.get(5)[2]++; // NO COMPAILATION ERROR
System.out.println(Arrays.toString(m.get(5))); // op: [2, 2, 3, 2]

Example 2:

HashMap<Integer, Integer> n = new HashMap<>();
n.put(6, 2);
n.get(6)++; // COMPILATION ERROR - Variable Expected 

Example 3:

 HashMap n = new HashMap();
 n.put(6, 2);
 n.get(6)++; // COMPILATION ERROR - Variable Expected

The value on a primitive int array can be mutated by just using the increment operator whereas the a Map with actual Integer (Ex 2,3) refuses this with a compilation error, why is that?

Note: I’m expected Example 2 to increment the value in the map. Just as in the below behaviour:

Integer x = 2; 
x++; 

Answer

According to JLS §15.1,

When an expression in a program is evaluated (executed), the result denotes one of three things:

  • A variable (in C, this would be called an lvalue)

  • A value

  • Nothing (the expression is said to be void)

And §15.14.2 says:

15.14.2. Postfix Increment Operator ++

A postfix expression followed by a ++ operator is a postfix increment expression.

The result of the postfix expression must be a variable of a type that is convertible to a numeric type, or a compile-time error occurs.

The important part is that the expression before the ++ must be a “variable“, not a “value” or “nothing”.

The method invocation expression m.get(6) denotes a “value”, whereas m.get(5)[2] denotes a “variable”. This is specified in §15.10.3:

The result of an array access expression is a variable of type T, namely the variable within the array selected by the value of the index expression.

On the other hand, in §15.12, where method invocation expressions are specified, it does not say that method invocation expressions are variables.

If you think about it, method calls have to be values and not variables Imagine if method calls produce variables and you had a method like:

public static int foo() {
    return 1;
}

And you did:

foo()++;

What would you be incrementing? The constant 1? Does 1 actually mean 2 now? That doesn’t make much sense, does it?