10

我试图了解nullJava 中的工作原理。

如果我们分配null给任何对象,幕后实际发生了什么?它是否分配了一个指向null“对象”或其他东西的内存位置地址?

我已经尝试了以下程序,并且我了解到所有nulls 都指向同一个位置。

但是谁能告诉我 Java 是如何抛出NullPointerException的以及在 Java 中是如何null工作的?

class Animal{
}

class Dog{
}


public class testItClass {

    public static void main(String args[]){
        Animal animal=null;
        Dog dog=null;

        if(((Object)dog) == ((Object)animal))
            System.out.println("Equal");
    }

}

输出

平等的。

4

8 回答 8

4

如果我们将 null 分配给任何对象,它实际上是堆中的某个内存位置或其他任何东西。

应该区分referenceobject。您可以分配null给参考。对象通常使用new运算符在堆中创建。它返回一个对象的引用。

A a = new A();

A在堆中创建具有类型的对象。给你回参考a。如果你现在分配

a = null;

对象本身仍驻留在堆中,但您将无法使用 reference 访问它a

请注意,对象可能稍后会被垃圾收集。

升级版:

我创建了这个类来查看它的字节码(对我来说是第一次):

public class NullTest {
    public static void main (String[] args) {
        Object o = new Object();
        o = null;
        o.notifyAll();
    }
}

它产生:

C:\Users\Nikolay\workspace\TestNull\bin>javap -c NullTest.class
Compiled from "NullTest.java"
public class NullTest {
  public NullTest();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #3                  // class java/lang/Object
       3: dup
       4: invokespecial #8                  // Method java/lang/Object."<init>":()V
       7: astore_1
       8: aconst_null
       9: astore_1
      10: aload_1
      11: invokevirtual #16                 // Method java/lang/Object.notifyAll:()V
      14: return
}

您可以看到将 null 设置为引用结果:

8: aconst_null
9: astore_1

字节码指令列表

基本上它将 null 的值放在堆栈的顶部,然后保存到引用。但是这种机制和参考实现是 JVM 内部的。

对java对象的引用是如何实现的?

于 2013-01-31T07:59:35.660 回答
1

以下声明对类Animal(或其子类)对象的引用,并将其初始化为null

Animal animal = null;

在这里,引用本身占用了一些空间。由于没有关联的对象,因此没有进一步的内存成本。

如果您尝试通过访问对象来使用null引用:

Animal cat = null;
if (cat.equals(dog)) { ... } // throws NPE

你会得到一个NullPointerException.

null但是,只要您不尝试取消引用它,就可以对引用本身进行操作:

Animal cat = null;
Animal dog = null
if (cat == dog) { ... }      // works fine
于 2013-01-31T07:58:47.377 回答
1

Java中的Null是基于NULL Object模式设计的。

NULL Object 表示不存在的对象。如果我们试图从这个不存在的对象访问任何资源,我们不应该得到任何东西,这在逻辑上是有道理的。但实际上像 Java 这样的编程语言会创建 NullPointerException 类的实例并将所需的信息填充到 Object 中并在调用语句处抛出。

于 2013-09-17T09:42:19.017 回答
0

当一个对象设置为nullthen 时,它在 JVM 中基本上没有内存引用。此外,==两个空对象之间的比较也会产生一个真值。

于 2013-01-31T08:02:06.023 回答
0

Java中只有一个null。它在所有出现的情况下都是相同的,无论变量如何,甚至无论类别如何。编译器不允许直接比较,但您可以强制转换:

String x = null;
ArrayList a = null;
if ((Object) x == (Object) a) {
  System.out.println("Do not have onther nulls, only ME");
}
于 2013-01-31T08:06:33.467 回答
0

Null 实际上是对任何内容的内存引用(因此为 null)。代码中的所有对象引用都是指向内存中保存物理数据的位置的指针。如果一个对象为空,则它没有引用,或者指向内存中的任何内容。这就是为什么除了检查它是否为空之外,null 不能用于其他任何事情。

当试图操作一个没有物理内存引用的对象时,Java 将抛出一个空异常。

于 2013-01-31T07:55:47.273 回答
0

它输出 true 因为null == null

Null 没有任何意义。

Animal animal=null;

定义对对象的引用Animal,但尚未分配给一个对象,因此它不指向任何对象。

如果您有 C/C++ 经验,这就像设置一个指向NULLor的指针nullptr

于 2013-01-31T07:59:02.650 回答
0

在字节码级别,有一条指令将“null”推送到本地堆栈(然后将其分配给变量槽或字段)。

大多数 Java 虚拟机实际上都在使用分配给 null 的真实(机器)指针。因此,如果使用它们,它们会在内部捕获信号(SIGSEGV)并将其转换为 NPE。实际上,您可以通过向 Java PID 发送“kill -SEGV”来测试它,它会在大多数情况下生成随机 NullPointerExceptions。

于 2014-07-25T23:57:51.343 回答