9

I've got a question.

public class Jaba {

    public static void main(String args[]) {
        Integer i = new Integer(0);        
        new A(i);
        System.out.println(i);
        new B(i);
        System.out.println(i);
        int ii = 0;        
        new A(ii);
        System.out.println(ii);
        new B(ii);
        System.out.println(ii);    
    }

}

class A {

    public A(Integer i) { ++i; }

}

class B {

    public B(int i) { ++i; }

}

To my mind passing an int\Integer as Integer to a function and making ++ on that reference should change the underlying object, but the output is 0 in all the cases. Why is that?

OneMoreVladimir
  • 1,653
  • 3
  • 21
  • 32

4 Answers4

12

Most of the classes such as Integer that derive from Java's abstract Number class are immutable., i.e. once constructed, they can only ever contain that particular number.

A useful benefit of this is that it permits caching. If you call:

Integer i = Integer.valueOf(n);

for -128 <= n < 127 instead of:

Integer i = Integer.new(n)

you get back a cached object, rather than a new object. This saves memory and increases performance.

In the latter test case with a bare int argument, all you're seeing is how Java's variables are passed by value rather than by reference.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 1
    Actually, the `Number` class simply is abstract and stateless - and there are subclasses that *are mutable* (AtomicInteger and AtomicLong are such ones, and one also could define new custom ones). – Paŭlo Ebermann Jul 03 '11 at 13:45
5

@Alnitak -> correct. And to add what really happens here. The ++i due to autoboxing works like that:

int val = Integer.intValue(); ++val;

and val is not stored anywhere, thus increment is lost.

Jarek Potiuk
  • 19,317
  • 2
  • 60
  • 61
3

As said in the other answers, Java does only call-by-value, and the ++ operator only effects a variable, not an object. If you want to simulate call-by-reference, you would need to pass a mutable object, like an array, and modify its elements.

The Java API has some specialized objects for this, like java.util.concurrent.atomic.AtomicInteger (which additionally also works over multiple threads), and org.omg.CORBA.IntHolder (used for call-by-reference for remote calls by the CORBA mechanism).

But you can also simply define your own mutable integer:

class MutableInteger {
    public int value;
}


class C {
   public C(int[] i) {
       ++i[0];
   }
}
class D {
   public D(MutableInteger i) {
       ++i.value;
   }
}
class E {
   public E(AtomicInteger i) {
       i.incrementAndGet();
   }
}
public class Jaba {
    public static void main(String args[]) {

        int[] iii = new int[]{ 0 };
        System.out.println(iii[0]);
        new C(iii);
        System.out.println(iii[0]);
        MutableInteger mi = new MutableInteger();
        System.out.println(mi.value);
        new D(mi);
        System.out.println(mi.value);
        MutableInteger ai = new AtomicInteger(0);
        System.out.println(ai);
        new E(ai);
        System.out.println(ai);
    }
}
Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
0

If you want to use reference parameter then try this.

IntHolder http://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/IntHolder.html

gun9
  • 71
  • 1
  • 4