在Java中,“this”可以为null吗?

在类方法中看到这一行,我的第一反应是嘲笑写它的开发人员。但是,然后,我想我应该确保我是对的第一。

public void dataViewActivated(DataViewEvent e) { if (this != null) // Do some work } 

这条线会评估为假?

不,它不能。 如果你使用this ,那么你在实例中,所以this不是null。

JLS说:

当用作主expression式时,关键字this表示一个值,该值是对实例方法被调用的对象(第15.12节)的引用,或者对正在构造的对象的引用。

如果你从一个对象中调用了一个方法,那么这个对象就存在了,否则你之前会有一个NullPointerException (或者它是一个静态方法,但是你不能使用它)。


资源:

  • JLS – this关键字

这就像问自己“我活着吗?” this永远不能为空

如果使用-target 1.3或更早版本进行编译,则外部可能为null 。 或者至less它曾经…

不,从来没有 ,关键字“this”本身代表该类的当前活动实例(对象)在该类的范围内,您可以访问它的所有字段和成员(包括构造函数)和其父类的可见的。

而且,更有趣的是,尝试设置它:

 this = null; 

想想吗? 怎么可能呢,难道不会像切断你正在坐的那个分支一样。 由于关键字“this”在类的范围内可用,因此只要您说this = null; 那么你基本上就是要求JVM释放分配给该对象的内存,这个操作在某些操作当中是不允许发生的,因为在完成该操作之后需要安全地返回。

而且,试图this = null; 将导致编译器错误。 原因很简单,Java(或任何语言)中的关键字永远不会被赋值,即关键字永远不会是赋值操作的左值。

其他的例子,你不能说:

 true = new Boolean(true); true = false; 

不。要调用一个类的实例的方法,实例必须存在。 该实例隐式作为parameter passing给方法, this引用。 如果thisnull那么就没有实例调用方法了。

语言强制执行是不够的。 虚拟机需要执行它。 除非VM强制执行它,否则可以编写一个编译器,在调用用Java编写的方法之前不强制执行空检查。 实例方法调用的操作码包括将此ref加载到堆栈,请参阅: http : //java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787 。 将这个replace为空引用确实会导致testing错误

在静态类方法中,“this”没有定义,因为“this”与实例关联而不是类。 我相信这会给编译器错误,试图在静态上下文中使用“this”关键字。

当您在null引用上调用方法时,将从Java VM抛出NullPointerException 。 这是通过规范,所以如果您的Java VM严格遵守规范, this将永远不会为null

一个正常的this在真正的Java代码1中永远不能为null ,你的例子使用正常的this 。 有关更多详细信息,请参阅其他答案。

一个合格的this 不应该null ,但是有可能打破这个。 考虑以下几点:

 public class Outer { public Outer() {} public class Inner { public Inner() {} public String toString() { return "outer is " + Outer.this; // Qualified this!! } } } 

当我们想创build一个Inner的实例时,我们需要这样做:

 public static void main(String[] args) { Outer outer = new Outer(); Inner inner = outer.new Inner(); System.out.println(inner); outer = null; inner = outer.new Inner(); // FAIL ... throws an NPE } 

输出是:

 outer is Outer@2a139a55 Exception in thread "main" java.lang.NullPointerException at Outer.main(Outer.java:19) 

表明我们尝试创build一个nullInner参照Outer失败。

事实上,如果你坚持“纯Java”的信封,你不能打破这个。

但是,每个Inner实例都有一个隐藏的final合成字段(称为"this$0" ),其中包含对Outer的引用。 如果你真的很棘手,可以使用“非纯”的方式来指定null

  • 你可以使用Unsafe来做到这一点。
  • 你可以使用本地代码(如JNI)来做到这一点。
  • 你可以使用reflection来做到这一点。

无论哪种方式,你这样做,最终的结果是Outer.thisexpression式将评估为null 2

简而言之,有资格的this可能是null 。 但是,如果您的程序遵循“纯Java”规则,则这是不可能的


1 – 我打折了一些技巧,比如手写“字节码”,然后把它们作为真正的Java传递出去,用BCEL或类似的方式调整字节码,或跳入本地代码,并用保存的寄存器进行处理。 国际海事组织,这不是Java。 假设,这样的事情也可能发生,因为一个JVM的bug …但我不记得每个看到的错误报告。

2 – 实际上,JLS并没有说出行为是什么,它可能是依赖于实现的。

tl; dr,“this”只能从非静态方法调用,我们都知道一个非静态方法是从某种不能为null的对象中调用的。