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


109

在类方法中看到了这行代码,我的第一反应是嘲笑编写它的开发人员。

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

那行会否评估为假?


104
总是先嘲笑,然后再提问。道歉要比抓住千载难逢的机会将某人砸成一片硫磺要容易得多。
乔尔·埃瑟顿

5
+1为“乱硫磺”一词。
马蒂·皮特

13
你知道有什么好笑的吗?由于编译器错误,这可能在C#中发生!
Blindy

1
@Blindy将为代码示例提供+1。
内森·费格

6
在C#中可以为null。在某些情况下。我有同样的冲动:嘲笑傻瓜,但后来我才平静下来。看看这里:stackoverflow.com/questions/2464097/...
安德烈Rînea

Answers:


88

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

JLS说:

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

如果从对象调用方法,则该对象存在或将具有NullPointerExceptionbefore(或它是静态方法,但不能this在其中使用)。


资源:


4
我对Java并不了解,但是在C ++中this,实例方法可以为NULL。因此,我不太相信这是Java中充分的理由。
kennytm

4
发现foo.bar()时,将抛出null指针异常。它确实在输入方法之前发生,但是真实的故事是没有尝试调用的方法。foonull
Claudiu 2010年

5
@KennyTM:在Java中就足够了。如果您正在使用this关键字并进行编译,则在观察时它不为null。但是就像其他人所说的那样,这在尝试调用该方法时不会阻止NPE,例如,但这完全超出了您的控制范围,并且该方法中的空检查不会改变任何内容。
Mark Peters

5
@Kenny:并非没有未定义的行为,尽管如果您知道实现的详细信息,则可以使用它。

4
即使完全有道理,我也不会赞成这个明确的答案。我有一个Android应用程序的崩溃报告,其中在从另一个线程对变量进行空值化后立即调用实例方法时,此== null。即使变量为null,实际调用也会通过,并且在尝试读取实例成员时会崩溃:)
Adrian Crețu

63

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


44
我还活着?上帝啊,我已经不知道了
克劳迪(Claudiu)2010年

您的声音听起来this != null不言而喻。对于非虚拟方法,例如,在C ++中this可能NULL不是。
Niki 2010年

1
@nikie从某种意义上说,这是不言而喻的。即使在C ++中,发生这种情况的任何程序都具有未定义的行为。对于GCC上的虚拟功能,也可能发生这种情况:ideone.com/W7RmU
Johannes Schaub-litb

8
@约翰:你是。折磨的一部分是您无法确认。

@ JohannesSchaub-litb带有空引用的c ++程序的行为未定义是不正确的。只要您不取消引用它,它就会被定义
Rune FS

9

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

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

this = null;

考虑一下吗?怎么可能,就像剪掉您坐在的树枝一样。由于关键字“ this”在类的范围内可用,因此只要您说this = null即可;在类中的任何位置,您基本上都是在要求JVM在某个操作的中间释放分配给该对象的内存,而JVM不允许发生这种情况,因为它需要在完成该操作后安全地返回。

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

其他示例,您不能说:

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

好解释的朋友。
Pankaj Sharma 2014年

@PankajSharma谢谢:)
sactiw 2014年

我找到这个是因为我想看看是否可以使用this = null。我的实例在android中,我想删除一个视图并将处理该视图的对象设置为null。然后,我想使用一种方法remove()来删除实际视图,然后使处理程序对象变得无用,因此我想将其为空。
Yokich

不确定我是否同意您的主张。(至少中间部分;左值部分很好...尽管我很确定实际上有残破的语言可以让您分配例如true = false(甚至我不会称之为残破的语言也可以使用它)反射或类似的欺骗手段))。无论如何,如果我有一些对象foo并且我打算做(忽略它是非法的)foo.this = null,则foo仍将指向内存,因此JVM不会对它进行垃圾回收。
Foon 2015年

@Foon很好,这个问题恰好是关于Java语言的,此外,我还没有遇到允许设置this = null的任何语言。也就是说,如果确实存在这样的语言,那么我高度怀疑这些语言中的“ this”是否具有相同的上下文和意识形态。
sactiw 2015年

7

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


2
我想通过反射我们可以将外部this设置为null。当他在引用中出现空指针异常时,可能是某人的愚人节笑话Outer.this.member
无可辩驳的2010年

3

否。要调用类的实例的方法,该实例必须存在。实例作为参数被隐式传递给方法,由引用this。如果this是,null则没有实例可调用方法。



3

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


2

普通this永远不能出现null在真实的Java代码1中,您的示例使用了普通的Java代码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参考其Outer失败。

实际上,如果您坚持使用“ Pure Java”信封,则不能破坏它。

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

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

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

总之,这是可能的有资格的thisnull。但是,如果程序遵循“纯Java”规则,则是不可能的


1-我不喜欢技巧,例如用手“编写”字节码并将其作为真正的Java传递出去,使用BCEL或类似方法调整字节码,或者跳入本机代码并使用已保存的寄存器进行处理。IMO,那不是Java。假设,这种情况也可能是由于JVM错误而发生的……但是我不记得每个看到的错误报告。

2-实际上,JLS并未说明行为将是什么,它可能取决于实现...等等。


1

当您调用引用方法时nullNullPointerException将从Java VM中抛出。这是按规范进行的,因此,如果您的Java VM严格遵守规范,则this绝对不会如此null


1

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

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


0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.