Java中的“this”可以为null吗?

时间:2010-09-24 17:29:02

标签: java this

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

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

该行是否会评估为假?

11 个答案:

答案 0 :(得分:84)

不,不能。如果您使用的是this,那么您就在实例中,因此this不为空。

JLS说:

  

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

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


资源:

答案 1 :(得分:61)

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

答案 2 :(得分:9)

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

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

this = null;

想一想?怎么可能,就像削减你所坐的分支一样。由于关键字“this”在类的范围内可用,因此只要你说this = null;在类中的任何地方,你基本上都要求JVM在某些操作过程中释放分配给该对象的内存,JVM不允许这样做,因为它需要在完成该操作后安全返回。

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

其他例子,你不能说:

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

答案 3 :(得分:7)

如果使用-target 1.3或更早版本进行编译,则外部 this可能为null。或者至少过去......

答案 4 :(得分:3)

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

答案 5 :(得分:3)

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

答案 6 :(得分:3)

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

答案 7 :(得分:1)

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

答案 8 :(得分:1)

普通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!!
       }
   }
}

当我们想要创建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)

显示我们尝试创建Inner null的{​​{1}}引用失败。

事实上,如果你坚持使用纯粹的Java"信封你不能打破这个。

但是,每个Outer实例都有一个隐藏的Inner合成字段(称为final),其中包含对"this$0"的引用。如果你真的很棘手,可以使用"非纯粹的"意味着将Outer分配给该字段。

  • 您可以使用null来执行此操作。
  • 您可以使用本机代码(例如JNI)来执行此操作。
  • 您可以使用反射来完成。

无论哪种方式,最终结果是Unsafe表达式将评估为Outer.this 2

简而言之,合格nullthis 可能。但如果您的程序遵循" Pure Java"那么不可能规则。

1 - 我打折等#34;写"手工操作字节码并将它们作为真正的Java传递出去,使用BCEL或类似方法调整字节码,或者跳转到本机代码并使用保存的寄存器进行处理。 IMO,这不是Java。假设这样的事情也可能由于JVM错误而发生......但我不记得每一个看到错误的报告。

2 - 实际上,JLS没有说出行为是什么,它可能依赖于实现......等等。

答案 9 :(得分:1)

如果该方法是静态的,则没有任何this。如果该方法是虚方法,则this不能为null,因为要调用该方法,运行时将需要使用this指针引用vtable。如果该方法是非虚拟,则可以,this为空。

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

答案 10 :(得分:0)

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