【问题标题】:Are Primitive Wrapper Classes in Java Treated as Reference Types?Java中的原始包装类是否被视为引用类型?
【发布时间】:2014-12-03 22:44:54
【问题描述】:

来自Java in a Nutshell, 2.10 Reference Types

Java 不直接操作对象和数组。相反,它 操作对对象和数组的引用。因为 Java 处理 引用的对象和数组,类和数组类型被称为 引用类型。相反,Java 处理原语的值 直接类型或按值类型。

但从下面看来,原始包装类(对象)实际上是通过值而不是引用来处理的,

> Integer foo = new Integer(1);
> Integer bar = foo;
> bar = new Integer(2);
> foo
1

那么上面的引用是不是不太对?


更新:我的困惑来自于误解了我上面的代码 sn-p 与以下代码之间的区别:

> import java.util.LinkedList;
> LinkedList<Integer> foo = new LinkedList<Integer>();
> foo.add(1);
> LinkedList<Integer> bar = foo;
> bar.remove(); 
> System.out.println(foo.size());
0
> System.out.println(bar.size());
0

在后一种情况下,bar.remove() 实际上在 foobar 引用的 LinkedList 上运行。

【问题讨论】:

  • 您分配给bar,而foo 不会改变。这不区分引用和值。

标签: java reference wrapper


【解决方案1】:

原始类包装器是对象引用,而不是原始类型。

在您的示例中,您正在为变量分配一个新值,而不是更新状态。这就是为什么foo 保持其 old 值(旧是因为它从未更改过):

Integer foo = new Integer(1);
Integer bar = foo; //bar and foo "points" to the same location
bar = new Integer(2); //now bar only "points" to a new location, foo is unaffected
System.out.println(foo);

您可以通过使用==equals 比较来轻松测试:

Integer a = 128;
Integer b = 128;
System.out.println(a == b); //false
System.out.println(a.equals(b)); //true

【讨论】:

  • 我们在使用== 查明事情时要非常小心;包装器类型有一个内置缓存,用于存储 -128 和 127 范围内的值。因此,将上面示例中的 128 替换为 127 将为两者打印true
  • @SanjayT.Sharma 我知道。这就是为什么我使用 128 而不是 127,这在其他 Q/As 中有解释。
【解决方案2】:

您的代码片段并未证明包装器的行为类似于值类型:事实上,它们是引用类型,并且它们是不可变的。

Integer foo = new Integer(1); // foo references an object wrapping 1
Integer bar = foo;            // bar references the same object as foo
bar = new Integer(2);         // bar references an object wrapping 2;
                              // continues to reference 1

查看原始包装器发生了什么的一种简单方法是使用== 运算符而不是调用equals 来比较它们是否相等。不过,您需要小心避免比较小数字的包装器,因为出于性能原因,它们会被缓存。

【讨论】:

    【解决方案3】:

    您链接的引用所指的是字段访问和数组访问表达式。那些需要通过参考值来确定底层对象。

    = 运算符被称为assignment operator. 在您的情况下,它不是字段访问表达式,也不是数组访问表达式,所以我们属于第三种情况

    • 首先,计算左侧操作数以生成变量。如果此评估突然完成,则赋值表达式 出于同样的原因突然完成;右手操作数不是 已评估并且没有分配发生。
    • 否则,将计算右侧操作数。如果此评估突然完成,则赋值表达式突然完成 出于同样的原因,没有分配发生。
    • 否则,将右侧操作数的值转换为左侧变量的类型,进行值集转换 (§5.1.13)到适当的标准值集(不是 扩展指数值集),转换的结果是 存储到变量中。

    所以在

    bar = new Integer(2);
    

    bar 被评估并产生一个变量,它本身。然后,必须评估new Integer(2)。那是new instance creation expression。它产生一个实例,其值为reference value

    引用值(通常只是引用)是指向这些的指针 对象,以及一个特殊的空引用,它不引用任何对象。

    生成该值后,将其分配给bar

    注意foo 从未参与其中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 2015-02-22
      • 1970-01-01
      • 2021-09-11
      • 2016-06-16
      • 1970-01-01
      相关资源
      最近更新 更多