5

I would like to pass a reference to a primitive type to a method, which may change it.

Consider the following sample:

public class Main {

    Integer x = new Integer(42);
    Integer y = new Integer(42);

    public static void main(String[] args) {
        Main main = new Main();
        System.out.println("x Before increment: " + main.x);

        // based on some logic, call increment either on x or y
        increment(main.x);

        System.out.println("x after increment: " + main.x);
    }

    private static void increment(Integer int_ref) {
        ++int_ref;
    }
}

The output running the sample is:

x Before increment: 42
x after increment: 42

Which means int_ref was past to the function by value, and not by reference, despite my optimistic name.

Obviously there are ways to work around this particular example, but my real application is way more complex, and in general one would imagine that a "pointer" or reference to integer would be useful in many scenarios.

I've tried to pass Object to the function (then casting to int), and various other methods, with no luck. One workaround that seems to be working would be to define my own version of Integer class:

private static class IntegerWrapper {
    private int value;

    IntegerWrapper(int value) { this.value = value; }
    void plusplus() { ++value; }
    int getValue() { return value; }
}

Doing this, and passing a reference to IntegerWrapper does work as expected, but to my taste it seems very lame. Coming from C#, where boxed variable just remain boxed, I hope I just miss something.

EDIT:

I would argue my question isn't a duplicate of Is Java "pass-by-reference" or "pass-by-value"?, as my question isn't theoretical, as I simply seek a solution. Philosophically, all method calls in all languages are pass-by-value: They either pass the actual value, or a reference to the value - by value.

So, I would rephrase my question: What is the common paradigm to workaround the issue that in java I'm unable to pass a reference to an Integer. Is the IntegerWrapper suggested above a known paradigm? Does a similar class (maybe MutableInt) already exist in the library? Maybe an array of length 1 a common practice and has some performance advantage? Am I the only person annoyed by the fact he can store a reference to any kind of object, but the basic types?

Uri London
  • 10,631
  • 5
  • 51
  • 81
  • 1
    Passing an `Integer` instead of an `int` doesn't mean passing by reference. Everything in java is pass-by-value. – BackSlash Nov 27 '18 at 14:28
  • Even object references are passed by value in Java. – khelwood Nov 27 '18 at 14:29
  • http://www.javadude.com/articles/passbyvalue.htm – QBrute Nov 27 '18 at 14:35
  • Every language has is quirks, and you should go along with them ... Your code cannot work, `++` operators acts on `int` and not on `Integer` and even if it did, `Integer` is immutable. You should just forget the word pointer in java, it does not belong to it. – minus Nov 27 '18 at 14:36
  • BTW `Integer` as all other primitive wrappers, are immutable (constants) - so you could not change its value, only its reference... and that is passed by value – user85421 Nov 27 '18 at 14:50
  • You need to use MutableInt from Apache commons lang. – rghome Nov 27 '18 at 14:58
  • If you describe your actual use case, there will probably be a good answer. There's no single workaround for all issues of this type. – khelwood Nov 27 '18 at 21:35
  • 1
    You could also use `AtomicInteger`. – MC Emperor Nov 27 '18 at 22:15
  • Your `increment` method would better *return* the modified number instead of `void`. It's always a better design when you see generated values as return values. I always have an odd feeling when you have to pass something in to actually get something out. (Very popular with collections ...) – Stefan Steinegger Dec 10 '18 at 09:37

1 Answers1

6

Integer is immutable, as you may notice.

Your approach with private static class IntegerWrapper is correct one. Using array with size 1 is also correct, but in practice I have never seen using array for this case. So do use IntegerWrapper.

Exactly the same implementation you can find in Apache org.apache.commons.lang3.mutable.MutableInt.

In your example you also can provide Main instance to the static method:

public class Main {

    private int x = 42;

    public static void main(String[] args) {
        Main main = new Main();
        incrementX(main);
    }

    private static void incrementX(Main main) {
        main.x++;
    }
}

And finally, from Java8 you could define an inc function and use it to increment value:

public class Main {

    private static final IntFunction<Integer> INC = val -> val + 1;

    private int x = 42;

    public static void main(String[] args) {
        Main main = new Main();
        main.x = INC.apply(main.x);
    }

}
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35