对于" dereferencing"是否有正式或权威的定义?在Java?

时间:2014-10-02 02:26:30

标签: java

来自C和C ++背景,我一直认为Java中的解除引用是通过其引用访问对象的过程。

例如," ref"是一个引用,当用于访问它引用的Integer对象时,它被取消引用:

    Integer ref = new Integer(7);     
    // Dereference "ref" to access the object it refers to.
    System.out.println(ref.toString()); 

当解除引用过程失败时会发生NullPointerExceptions:

Integer ref = null;
// Dereferencing "ref" causes an exception.
System.out.println(ref.toString()); 

但是,我的解释与Oracle新Java SE 8 Programmer I exam (beta)上测试的其中一个主题相冲突:

  
    

解释对象的生命周期(创建," 通过重新分配取消引用"和垃圾收集)

  

因此,根据创建Java 8考试的人,在Java中取消引用是重新分配参考的行为,而不是评估参考的行为:

例如:

    // Create an Integer object, and a reference to it.
    Integer ref = new Integer(7); 
    ref = null; 
    // Now (according to Oracle?):
    // - The reassignment means ref has been "dereferenced".
    // - The dereferenced object is now eligible for Garbage Collection.

谷歌搜索这个问题表明甲骨文的定义被更广泛地使用,但这并不意味着它是正确的,并且是谷歌唯一一个通过重新分配来解除引用的定义"是为了新的Java 8考试!无论如何,JLS并没有真正解决任何问题。

对于解除引用在Java中的真正含义,是否存在任何正式或权威的定义(与个人意见相对)? (即它与评估或重新分配有关吗?)

两个完全不同的定义设法共存似乎很奇怪。

4 个答案:

答案 0 :(得分:4)

Java变量是"原始类型"或"参考类型"在Oracle's terminology中(除了特殊类型的null之外)。我从C ++背景来到Java并且总是发现最容易想到像指针这样的引用类型,因为它最容易理解它们是如何工作的(虽然有important differences),但是因为所有非原始变量都像没有评估的概念(没有相当于C ++的指针解除引用)。

所以,在你的例子中:

Integer ref = new Integer(7); 
ref = null;

在第一行,在堆上创建一个对象,ref引用它。 在第二行,ref被更改为引用null。堆上的对象没有更多的引用,因此它将有资格进行垃圾收集,但是直到垃圾收集器这样做,它实际上仍然存在(不包括这个简单示例的任何聪明的JVM优化!)。

AFAIK没有" dereferencing"的官方定义。在Java中。因为评估和分配之间没有区别,所以它确实有意义,尽管它不是我认为广泛使用的术语。

答案 1 :(得分:4)

虽然没有官方定义,但是“取消引用”这个词已经没有了。用于某些Java错误语句。

例如,如果您编写以下代码:

char ch = 'A';
if (ch.isLetter()) { }

您收到错误:char cannot be dereferenced

因此,可以说在.运算符的帮助下使用其引用访问对象的状态或行为是解除引用。

答案 2 :(得分:1)

<块引用>

Java 中的“解引用”是否有正式或权威的定义?

没有

您可以找到“取消引用”的正式定义的地方是 JLS 或 JVMS。我找了一下,没找到。


我的直觉理解是,取消引用是从引用到(松散地)引用“指向”的事物组件的过程。

以下是一些示例:

x = a.b;  // dereferences the value of 'a' to get the value of field 'b'
a.b();    // dereferences the value of 'a' to get the method 'b'
x = a[1]; // dereferences the value of 'a' to an array and then subscripts it
a[1] = 2; // dereferences the value of 'a' to an array, subscripts it
          // then assigns to the cell

// dereferences the value of 'l' to an object and acquires the
// object's primitive lock
synchronized (l) {

简而言之,每当您执行可能引发 NPE 的原始操作时,涉及取消引用。

请注意,这既不是“分配参考”也不是(准确地说)“评估参考”。例如:

boolean truth = ...
String s = truth ? "yes" : null;

涉及评估三个引用值表达式并分配一个引用,但没有取消引用。不会抛出 NPE ...


好的,那么是否支持我在 Java 规范中对“取消引用”的解释?我声称有。

JLS 第 17 章包含我在最新版 JLS 中可以找到的术语“取消引用”的唯一用法。在 JLS 17.5.1 中,final 的语义被描述为 “受解引用链影响”,其定义如下:

<块引用>

"解引用链:如果操作 a 是未初始化 o 的线程 t 读取或写入对象 o 的字段或元素1}},那么必须存在一些被线程 r 读取的 t,它看到 o 的地址,使得 r dereferences(r, a)。”

如果你解开它的实际意思(在其上下文中),我声称他们正在以与我的第一个例子一致的方式使用术语取消引用

这也符合解引用运算符*)在C和C++中的含义;见Wikipedia。我还可以在其他 Oracle 文档中找到以这种方式使用的取消引用示例;例如Key Features of the Object-Relational Model > Dereferencing REFs

答案 3 :(得分:0)

取消引用的另一个例子是:

String value; // the pointer

value = new String("Value 1");
// a "Value 1" String instance is created, referenced by "value" pointer

value = new String("Value 2"); 
// a new String instance created; "value" pointer is re-assigned to it
// the "Value 1" instance is now de-referenced

value = null;
// "Value 2" String instance is de-referenced

当一个对象不再被引用时,它可能会被垃圾回收 集电极。重新分配给 null 类型的其他实例都将取消引用该实例。