2015-04-04 64 views
5

我总是理解静态变量在引用它们时共享一个实例。我想把这个测试结果告诉我,但结果与我预期的不同。增加一个整型变量不会影响另一个引用同一个对象的变量

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,问题在哪里?

+0

它们都是基元而不是对象。 'test'最初是'0',如果你想增加测试,你需要调用'test ++'。 – 2015-04-04 23:18:23

回答

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通过Integer.valueOf(int)并将该值转化为Integer,到Integer对象的引用存储在a。然后对a进行评估,产生对Integer对象的引用的值,并将该值存储在b中。

这是

还讨论相同的概念,事实的变量是static是无关紧要的。

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

counter++; 
test = counter; 
+0

是否有一个JLS引用说明了将盒装类型明确分配给其他盒装类型的转换?我环顾四周,找不到它。 – merlin2011 2015-04-04 23:31:47

+1

@ merlin2011你的意思是[拳击转换](http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.7)? – 2015-04-04 23:32:28

+0

只谈''整数''整数'和'整数'谈'整型'后的部分。在这里,我们将'Integer'看作'Integer'直接赋值,这是我无法找到的参考。 – merlin2011 2015-04-04 23:33:25

1

test不参考counter。它具有相同的初始值int是一个原始的。

0

test不是指针到counter:要设置其值等于初始计数器,但之后counter任何更改都不会在test的值中反映出来。

如果你想有两个引用到相同的可变值,你可以使用像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 
+0

因为不符合规格。 – 2015-04-04 23:20:57

-2

你需要一个原始和引用的区分-目的。整数不是原始的“本质”,但由于'boxing',它们具有特殊属性。你有什么是一个原始的intValue()因此它得到的初始值(它没有更多的关系到计数器)。

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

2

这是我的理解。

  • 第1步:当你说Integer counter = 0;你实际上做的是
    Integer counter = new Integer(0); 在这里你创建了一个Integer object,其值在0和counter被reffering它。
  • 步骤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引用新对象时,它将取消引用旧值为Integer object的值为0的值。但参考变量test仍旧保留旧Integer object。这就是test打印旧值的原因。

Java的的valueOf()从库Integer类方法

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