在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
引用。 如果this
是null
那么就没有实例调用方法了。
语言强制执行是不够的。 虚拟机需要执行它。 除非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一个null
的Inner
参照Outer
失败。
事实上,如果你坚持“纯Java”的信封,你不能打破这个。
但是,每个Inner
实例都有一个隐藏的final
合成字段(称为"this$0"
),其中包含对Outer
的引用。 如果你真的很棘手,可以使用“非纯”的方式来指定null
。
- 你可以使用
Unsafe
来做到这一点。 - 你可以使用本地代码(如JNI)来做到这一点。
- 你可以使用reflection来做到这一点。
无论哪种方式,你这样做,最终的结果是Outer.this
expression式将评估为null
2 。
简而言之,有资格的this
可能是null
。 但是,如果您的程序遵循“纯Java”规则,则这是不可能的 。
1 – 我打折了一些技巧,比如手写“字节码”,然后把它们作为真正的Java传递出去,用BCEL或类似的方式调整字节码,或跳入本地代码,并用保存的寄存器进行处理。 国际海事组织,这不是Java。 假设,这样的事情也可能发生,因为一个JVM的bug …但我不记得每个看到的错误报告。
2 – 实际上,JLS并没有说出行为是什么,它可能是依赖于实现的。
tl; dr,“this”只能从非静态方法调用,我们都知道一个非静态方法是从某种不能为null的对象中调用的。