Java Null行为

时间:2013-01-31 07:51:02

标签: java null nullpointerexception

我试图理解null在Java中是如何工作的。

如果我们将null分配给任何对象,那么场景背后会发生什么?它是否指定了指向null“对象”或其他内容的内存位置地址?

我已经尝试了以下程序,并且我已经明白所有null都指向同一位置。

但有人能告诉我Java如何抛出NullPointerException以及null如何在Java中运行?

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");
    }

}

输出

相等。

8 个答案:

答案 0 :(得分:4)

  

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

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

A a = new A();

在堆中创建类型为A的对象。您将获得返回参考a。如果现在你指定

a = null;

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

请注意,以后可能会对对象进行垃圾回收。

<强> UPD:

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

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

List of byte code instructions

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

How is reference to java object is implemented?

答案 1 :(得分: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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

它输出true,因为null == null

空无意义。

Animal animal=null;

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

如果您有使用C / C ++的经验,就像设置指向NULLnullptr的指针。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

String x = null;
ArrayList a = null;
if ((Object) x == (Object) a) {
  System.out.println("Do not have onther nulls, only ME");
}

答案 7 :(得分:0)

在字节码级别上有一条指令来推送&#34; null&#34;到本地堆栈(然后将其分配给可变插槽或字段)。

大多数Java虚拟机实际上使用分配给null的实际(机器)指针。因此,如果使用它们,它们会在内部捕获信号(SIGSEGV)并将其转换为NPE。你可以通过发送&#34; kill -SEGV&#34;来测试这个。对于Java PID,它将在大多数时间生成随机NullPointerExceptions。