有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中的原始包装器类是否被视为引用类型?

Java in a Nutshell, 2.10 Reference Types

Java does not manipulate objects and arrays directly. Instead, it manipulates references to objects and arrays. Because Java handles objects and arrays by reference, classes and array types are known as reference types. In contrast, Java handles values of the primitive types directly, or by value.

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

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

那么,上面的引述是否不完全正确


更新:我的困惑是因为误解了上面的代码片段和下面的代码片段之间的区别:

> 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上操作


共 (3) 个答案

  1. # 1 楼答案

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

    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来比较它们是否相等。不过,您需要小心避免比较小数字的包装,因为出于性能原因,它们是缓存的

  2. # 2 楼答案

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

    =操作符称为assignment operator.。在您的例子中,它不是字段访问表达式,也不是数组访问表达式,因此我们使用第三种情况

    • First, the left-hand operand is evaluated to produce a variable. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason; the right-hand operand is not evaluated and no assignment occurs.
    • Otherwise, the right-hand operand is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
    • Otherwise, the value of the right-hand operand is converted to the type of the left-hand variable, is subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.

    所以在

    bar = new Integer(2);
    

    bar进行求值并生成一个变量本身。然后,必须对new Integer(2)进行求值。这是一个new instance creation expression。它生成一个值为reference value的实例

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

    生成该值后,它将被分配给bar

    请注意foo是如何从不涉及的

  3. # 3 楼答案

    基本类包装器是对象引用,而不是基本类型

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

    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