代码之家  ›  专栏  ›  技术社区  ›  Bryce Fischer

“这个”在Java中永远是空的吗?

  •  102
  • Bryce Fischer  · 技术社区  · 14 年前

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

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

    那条线会被认为是错误的吗?

    10 回复  |  直到 7 年前
        1
  •  83
  •   Colin Hebert    14 年前

    不行,如果你用 this ,那么你就在这个例子中,所以 不为空。

    JLS说:

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

    如果从对象调用方法,则该对象存在,或者 NullPointerException 以前(或是静态方法,但之后,不能使用 在里面)。


    资源:

        2
  •  61
  •   NullUserException Mark Roddy    14 年前

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

        3
  •  9
  •   user3071284    9 年前

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

    更有趣的是,尝试设置:

    this = null;
    

    想想看?这怎么可能呢,难道不是像剪断你坐着的树枝那样吗?因为关键字“this”在类的范围内是可用的,所以只要您说this=null;在类内的任何地方,那么您基本上都会要求jvm在某些操作的中间释放分配给该对象的内存,而jvm只是不允许这些操作发生,因为它需要返回。完成操作后安全。

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

    其他例子,你不能说:

    true = new Boolean(true);
    true = false;
    
        4
  •  7
  •   Leon Timmermans    14 年前

    如果用 -target 1.3 或者更早,然后 外面的 this 可能是 null . 或者至少它曾经…

        5
  •  3
  •   Claudiu    14 年前

    否。若要调用类的实例的方法,该实例必须存在。实例作为参数隐式传递给方法,由引用 this . 如果 null 那么就没有实例可以调用的方法了。

        6
  •  3
  •   Rune FS    12 年前

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

        7
  •  3
  •   Sai Kishore Omnaest    7 年前

    在静态类方法中, this 未定义,因为 与实例而不是类相关联。我相信如果尝试使用 静态上下文中的关键字。

        8
  •  1
  •   tia    14 年前

    当对调用方法时 null 参考文献 NullPointerException 将从Java虚拟机中抛出。按照规范,如果您的Java VM严格遵守规范, this 永远不会 无效的 .

        9
  •  1
  •   Stephen C    8 年前

    正常的 this 永远不会 null 在真正的Java代码中 ,您的示例使用 . 更多详情请参阅其他答案。

    合格的 应该 永远不会 无效的 但有可能打破这一点。考虑以下事项:

    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)
    

    显示我们试图创建一个 用一个 无效的 参考ITS Outer 失败了。

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

    但是,每个 实例具有隐藏的 final 合成场 "this$0" )其中包含对 . 如果你真的很棘手,可以用“非纯”的方式来分配 无效的 去球场。

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

    不管怎样,最终的结果是 Outer.this 表达式的值将为 无效的 .

    简而言之,它 是可能的 对于一个合格的 成为 无效的 . 但它是 不可能的 如果你的程序遵循“纯Java”规则。


    1 -我打折技巧,如“写”字节码的手,并传递它们作为真正的Java,调整字节码使用BCEL或类似,或跳转到本机代码和欺骗与保存的寄存器。IMO,那不是Java。假设,这样的事情也可能是由于一个JVM错误…但我不记得所有看到的错误报告。

    2-事实上,JLS没有说明行为将是什么,它可能依赖于实现…除此之外。

        10
  •  0
  •   Adam    14 年前

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