“ this”在 Java 中会是 null 吗?

在类方法中看到这一行,我的第一反应是嘲笑编写它的开发人员。.但后来,我觉得我应该先确定自己是对的。

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

这条线会被评价为假吗?

26507 次浏览

不,它不能。如果您正在使用 this,那么您在实例中,所以 this不为空。

劳工统计局表示:

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

If you invoked a method from an object, then the object exists or you would have a NullPointerException before (or it's a static method but then, you can't use this in it).


资源:

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

没有。要调用类实例的方法,该实例必须存在。该实例作为参数隐式传递给方法,由 this引用。如果 thisnull,那么就没有实例来调用。

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

如果你用 -target 1.3或更早的版本编译,那么 外面this可能是 null。或者至少它曾经是..。

null引用上调用方法时,将从 JavaVM 抛出 NullPointerException。这是由规范决定的,所以如果您的 JavaVM 严格遵守规范,那么 this永远不会是 null

“ this”只能从非静态方法调用,我们都知道非静态方法是从某种不能为空的对象调用的。

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

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

更有趣的是,试着设置:

this = null;

考虑一下?这怎么可能呢,难道不是像砍树枝一样吗。因为关键字‘ this’在类的作用域内是可用的,所以只要你说 this = null; 在类的任何地方,你基本上是在要求 JVM 在某个操作中释放分配给该对象的内存,而 JVM 不允许这样做,因为它需要在完成该操作后安全返回。

此外,尝试 this = null;将导致编译器错误。原因很简单,Java (或任何语言)中的关键字永远不能被赋值,也就是说,关键字永远不能是赋值操作的左值。

其他的例子,你不能说:

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

在实际的 Javacode1中,普通的 this永远不可能是 null,您的示例使用的是普通的 this。有关详细信息,请参阅其他答案。

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

public class Outer {
public Outer() {}


public class Inner {
public Inner() {}


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

When we want to create an instance of Inner, we need to do this:

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
}

The output is:

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

表明我们尝试创建一个 Inner与其 Outernull引用已经失败。

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

However, each Inner instance has a hidden final synthetic field (called "this$0") that contains the reference to the Outer. If you are really tricky, it is possible to use "non-pure" means to assign null to the field.

  • 你可以用 Unsafe来做。
  • 您可以使用本机代码(例如 JNI)来完成这项工作。
  • 你可以通过使用反射来做到这一点。

无论采用哪种方法,最终结果都是 Outer.this表达式的计算结果为 null2

简而言之,合格的 thisnull,它是 是可能的。但是如果您的程序遵循“纯 Java”规则,那么它就是 不可能


1 - I discount tricks such as "writing" the bytecodes by hand and passing them off as real Java, tweaking bytecodes using BCEL or similar, or hopping into native code and diddling with the saved registers. IMO, that is NOT Java. Hypothetically, such things might also happen as a result of a JVM bug ... but I don't recall every seeing bug reports.

实际上,JLS 并没有说明行为将是什么,而且它可能与实现有关... ... 还有其他一些因素。

如果该方法是静态的,则不存在任何 this。如果该方法是虚方法,那么 this不能为空,因为为了调用该方法,运行时将需要使用 this指针引用 vtable。如果方法是 not virtual,那么,是的,this可能为空。

C # 和 C + + 允许非虚方法,但是在 Java 中所有非静态方法都是虚方法,因此 this永远不会为空。