Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A reference to primitive type in Java (How to force a primitive data to remain boxed)

Tags:

java

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?

like image 324
Uri Avatar asked Nov 27 '18 14:11

Uri


1 Answers

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);
    }

}
like image 114
oleg.cherednik Avatar answered Sep 25 '22 23:09

oleg.cherednik