来自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中的真正含义,是否存在任何正式或权威的定义(与个人意见相对)? (即它与评估或重新分配有关吗?)
两个完全不同的定义设法共存似乎很奇怪。
答案 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 类型的其他实例都将取消引用该实例。