递增Integer变量不会影响引用同一对象的另一个变量

时间:2015-04-04 23:17:10

标签: java

我总是理解静态变量在引用时共享一个实例。我想对此进行测试,但结果与我预期的不同。

static Integer counter = 0;
static Integer test = counter;

public static void main(String args[]) {
     counter++;
     System.out.println("counter: " + counter);
     System.out.println("test: " + test);
}

输出:

  

计数器:1

     

测试:0

由于test引用counter我认为当我增加counter时,test也将自动增加。但是,似乎test从某个地方引用0,问题是,在哪里?

5 个答案:

答案 0 :(得分:4)

  

由于test引用counter

这种假设是错误的。在Java中,您不能引用变量。存储在变量中的是一个值。该值可以是基本类型值或引用类型值。在基元的情况下,该值是基元的值。在参考类型的情况下,

  

The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.

int a = 0;
int b = a;

评估变量a以生成值0,该值存储在b中。

Integer a = 0;
Integer b = a;

0转换为IntegerInteger.valueOf(int),值Integer对象的引用存储在a中。然后评估a,生成对Integer对象的引用值,该值存储在b中。

这与

中讨论的概念相同

此外,变量static这一事实无关紧要。

解决这个问题的唯一方法是手动更新test

counter++; 
test = counter;

答案 1 :(得分:2)

这是我的理解。

  • 第1步:当您说Integer counter = 0;您实际在做的是什么时 Integer counter = new Integer(0);        在这里,您创建了一个Integer object,其值为0,counter正在为此提供帮助。
  • 第2步: Integer test = counter;

    现在test也指同一个Integer object我们 在步骤1中创建。

  • 第3步:这是棘手的部分。在主方法中执行counter++;时,Java 自动装箱自动装箱 功能正在为您实现以下代码。

    counter = Integer.valueOf(counter.intValue() + 1);

由于Integer类在Java中是不可变的,当值从0递增到1时,valueOf()方法正在创建一个新的Integer object并存储其中的新值为1而不是更改旧对象的值(请参阅下面的Java的 valueOf()方法实现)。当您使用counter引用新对象时,它会取消引用其值为0的旧Integer object。但引用变量test仍然保留旧的Integer object 。这是test打印旧值的原因。

来自库类Integer的Java的valueOf()方法

638     public static Integer More ...valueOf(int i) {
639         assert IntegerCache.high >= 127;
640         if (i >= IntegerCache.low && i <= IntegerCache.high)
641             return IntegerCache.cache[i + (-IntegerCache.low)];
642         return new Integer(i); //See, new object is created here.
643     }

请参阅下文,了解详细的图解说明。

实线表示参考变量仍然保持对象。

虚线表示引用变量不再持有对象。

enter image description here

答案 2 :(得分:1)

test没有引用counter。它具有相同的初始值。 int是原始的。

答案 3 :(得分:0)

test不是指向counter的指针:您将其值设置为最初等于计数器,但counter的任何后续更改都不会反映在test的值中{1}}。

如果你想对同一个可变值有两个引用,你可以使用像AtomicInteger这样的东西:

static AtomicInteger counter = new AtomicInteger(0);
static AtomicInteger test = counter;
public static void main(String args[]) {
     counter.incrementAndGet();
     System.out.println("counter: " + counter);
     System.out.println("test: " + test);
}

输出:

counter: 1
test: 1

答案 4 :(得分:-2)

您需要区分基元和引用对象。整数不是原始的'per-se',但由于'boxing',它们具有特殊属性。你拥有的是intValue()的原语,因此它获得了初始值(它与计数器没有更多关系)。

嗯......对于记录'降级':OP已将他的字段从'int'更改为'Integers',因此我的初始答案不正确。