Ссылка java Integer

У меня вопрос.

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

}

На мой взгляд, передача int\Integer как целого в функцию и создание ++ в этой ссылке должно изменить базовый объект, но вывод равен 0 во всех случаях. Почему это?

Ответ 1

Как сказано в других ответах, Java выполняет только call-by-value, а оператор ++ обрабатывает только переменную, а не объект. Если вы хотите симулировать call-by-reference, вам нужно передать изменяемый объект, например массив, и изменить его элементы.

Java API имеет для этого несколько специализированных объектов, таких как java.util.concurrent.atomic.AtomicInteger (который также работает и над несколькими потоками) и org.omg.CORBA.IntHolder (используется для вызова по ссылке для удаленных вызовов с помощью механизма CORBA).

Но вы также можете просто определить свое собственное изменяемое целое число:

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

Ответ 2

Большинство классов, таких как Integer, которые выводятся из абстрактного класса Java Number, являются неизменяемыми, т.е. после их построения, они могут содержать только это конкретное число.

Полезным преимуществом этого является то, что он позволяет кэшировать. Если вы вызываете:

Integer i = Integer.valueOf(n);

для -128 <= n < 127 вместо:

Integer i = Integer.new(n)

вы возвращаете кешированный объект, а не новый объект. Это экономит память и повышает производительность.

В последнем тестовом примере с голой аргументом int все, что вы видите, это то, как переменные Java передаются по значению, а не по ссылке.

Ответ 3

@Alnitak → правильный. И добавить, что на самом деле происходит здесь. ++ я из-за autoboxing работает так:

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

и val не хранится нигде, поэтому приращение теряется.