2010-09-24 2 views
96

Nhìn thấy dòng này trong một phương pháp lớp học và phản ứng đầu tiên của tôi là chế giễu nhà phát triển đã viết nó .. Nhưng sau đó, tôi figured tôi nên chắc chắn rằng tôi đã đúng đầu tiên.Có thể "điều này" không bao giờ là rỗng trong Java?

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

Dòng đó có bao giờ được đánh giá là sai không?

+99

Luôn chế giễu trước và đặt câu hỏi sau. Thật dễ dàng để xin lỗi hơn là lấy lại một cơ hội vàng để xé một ai đó xuống trong một loạt đá sa thạch. –

+0

Tôi cũng nghĩ vậy ... Thực ra phải kiểm tra chú thích để đảm bảo nó không phải là của tôi ... Đã bao nhiêu lần tôi viết: –

+5

+1 cho thuật ngữ "flurry of brimstone". –

Trả lời

78

Không, không thể. Nếu bạn đang sử dụng this, thì bạn đang ở trong trường hợp như vậy this không phải là rỗng.

Các JLS nói:

Khi sử dụng như một biểu hiện ban đầu, từ khóa này biểu thị một giá trị đó là một tham chiếu đến đối tượng mà các phương pháp dụ được gọi (§15.12), hoặc cho các đối tượng đang được xây dựng.

Nếu bạn gọi một phương pháp từ một đối tượng, sau đó các đối tượng tồn tại hoặc bạn sẽ có một NullPointerException trước (hoặc đó là một phương pháp tĩnh nhưng sau đó, bạn không thể sử dụng this trong nó).


Resources:

+0

Sử dụng nó có thể, tuy nhiên, không biên dịch được. Nếu nó biên dịch thì nó an toàn để sử dụng. –

+0

Nó chỉ là vô nghĩa để làm kiểm tra như vậy hoặc là nó thực sự ngăn chặn bởi ngôn ngữ java mà một điều như vậy có thể xảy ra? I.e là ngoại lệ con trỏ null được ném trước khi nhập phương thức hoặc chỉ khi một thành viên được cố gắng truy cập? Trong các tình huống tương đương trong các ngôn ngữ khác (đặc biệt là C++), trường hợp này là hành vi không xác định và ngôn ngữ sẽ không chủ động ngăn chặn một kịch bản như vậy. –

+4

Tôi không biết sâu về Java, nhưng trong C++, 'this' của một phương thức instance có thể là NULL. Vì vậy, tôi không hoàn toàn tin rằng đây là một lý do đầy đủ trong Java. – kennytm

57

Nó giống như tự hỏi "Tôi còn sống?" this không bao giờ có thể là

+38

_am_ Tôi còn sống ?! o Thiên Chúa tôi không biết nữa – Claudiu

+7

Cogito ergo sum –

+7

Tổng số này ... –

3

No. Để gọi một phương thức của một thể hiện của một lớp, cá thể phải tồn tại. Ví dụ này được ngầm truyền như một tham số cho phương thức, được tham chiếu bởi this. Nếu thisnull thì sẽ không có trường hợp nào để gọi phương thức.

2

Trong phương pháp lớp tĩnh, this không được xác định vì this được liên kết với các phiên bản chứ không phải các lớp. Tôi tin rằng nó sẽ cung cấp cho một lỗi biên dịch để cố gắng sử dụng từ khóa this trong ngữ cảnh tĩnh.

7

Nếu bạn biên dịch với -target 1.3 hoặc sớm hơn, sau đó một ngoàithis có thể null. Hoặc ít nhất nó được sử dụng để ...

+2

Tôi đoán qua sự phản chiếu, chúng ta có thể thiết lập điều này thành rỗng. có thể là một trò đùa ngu ngốc tháng tư trên một người nào đó khi ông có ngoại lệ con trỏ null trong tham chiếu 'Outer.this.member' – irreputable

1

Khi bạn gọi phương thức trên tham chiếu null, NullPointerException sẽ được ném từ Java VM. Điều này là do đặc điểm kỹ thuật vì vậy nếu máy ảo Java của bạn tuân thủ nghiêm ngặt đặc điểm kỹ thuật, this sẽ không bao giờ là null.

0

tl; dr, "this" chỉ có thể được gọi từ một phương thức không tĩnh và chúng ta đều biết rằng một phương thức không tĩnh được gọi từ một số loại đối tượng không thể rỗng.

3

Không đủ để ngôn ngữ thực thi nó. VM cần thực thi nó. Trừ khi VM thi hành nó, bạn có thể viết một trình biên dịch không thực thi kiểm tra null trước khi gọi phương thức được viết bằng Java. Các opcodes cho một lời gọi phương thức thể hiện bao gồm tải ref này vào stack xem: http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787.Thay thế điều này cho một tham chiếu rỗng thực sự sẽ dẫn đến thử nghiệm là false

7

Không bao giờ, từ khóa 'this' đại diện cho đối tượng hiện tại (đối tượng) của lớp đó trong phạm vi của lớp đó. có thể truy cập tất cả các trường và thành viên của nó (bao gồm cả các hàm tạo) và các thành phần hiển thị của lớp cha của nó.

Và thú vị hơn, hãy thử cài đặt nó:

this = null; 

Hãy suy nghĩ về nó? Làm thế nào nó có thể là có thể, nó sẽ không giống như cắt cành bạn đang ngồi. Vì từ khóa 'this' có sẵn trong phạm vi của lớp nên ngay khi bạn nói điều này = null; bất cứ nơi nào trong lớp, sau đó bạn về cơ bản yêu cầu JVM giải phóng bộ nhớ được gán cho đối tượng đó ở giữa một số hoạt động mà JVM không thể cho phép xảy ra vì nó cần quay trở lại an toàn sau khi hoàn thành thao tác đó.

Hơn nữa, cố gắng this = null; sẽ dẫn đến lỗi trình biên dịch. Lý do khá đơn giản, một từ khóa trong Java (hoặc bất kỳ ngôn ngữ nào) không bao giờ được gán một giá trị tức là một từ khóa không bao giờ có thể là giá trị bên trái của một phép toán gán.

ví dụ khác, bạn không thể nói:

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

Người bạn giải thích tốt. –

+0

@PankajSharma Cảm ơn :) – sactiw

+0

Tôi đã tìm thấy điều này vì tôi muốn xem liệu tôi có thể sử dụng 'this = null' không. Ví dụ của tôi ở trong android nơi tôi muốn xóa chế độ xem và đặt đối tượng xử lý chế độ xem thành không. Sau đó, tôi muốn sử dụng một phương thức 'remove()' để loại bỏ khung nhìn thực tế và sau đó đối tượng xử lý sẽ được trả về vô dụng, vì vậy tôi muốn vô hiệu nó. – Yokich

0

Một bình thường this bao giờ có thể null trong mã Java thực , và ví dụ của bạn sử dụng một bình thường this. Xem các câu trả lời khác để biết thêm chi tiết.

Đủ điều kiện thisnên không bao giờ là null, nhưng có thể phá vỡ điều này. Hãy xem xét những điều sau đây:

public class Outer { 
    public Outer() {} 

    public class Inner { 
     public Inner() {} 

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

Khi chúng tôi muốn tạo ra một thể hiện của Inner, chúng ta cần phải làm điều này:

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 
} 

Đầu ra là:

outer is [email protected] 
Exception in thread "main" java.lang.NullPointerException 
     at Outer.main(Outer.java:19) 

cho thấy nỗ lực của chúng tôi để tạo một số Inner với tham chiếu null vào số Outer của nó không thành công.

Thực tế, nếu bạn dính trong phong bì "Pure Java", bạn không thể phá vỡ nó.

Tuy nhiên, mỗi trường hợp Inner có trường tổng hợp ẩn final ẩn (được gọi là "this$0") có chứa tham chiếu đến Outer. Nếu bạn thực sự khó khăn, có thể sử dụng "không thuần khiết" có nghĩa là chỉ định null cho trường này.

  • Bạn có thể sử dụng Unsafe để thực hiện.
  • Bạn có thể sử dụng mã gốc (ví dụ: JNI) để thực hiện.
  • Bạn có thể làm điều đó bằng cách sử dụng phản chiếu.

Dù bằng cách nào bạn làm điều đó, kết quả cuối cùng là sự biểu hiện Outer.this sẽ đánh giá để null .

Tóm lại, nó là có thể cho một đủ điều kiện thisnull. Nhưng đó là không thể nếu chương trình của bạn tuân thủ các quy tắc "Pure Java".


1 - Tôi giảm giá thủ đoạn như "viết" các bytecode bằng tay và đi qua chúng như Java thực, tinh chỉnh bytecode sử dụng BCEL hoặc tương tự, hoặc nhảy vào mã nguồn gốc và lừa gạt chính các thanh ghi lưu. IMO, đó KHÔNG phải là Java. Theo giả thuyết, những thứ như vậy cũng có thể xảy ra do lỗi JVM ... nhưng tôi không nhớ mọi báo cáo lỗi đang thấy.

2 - Thực ra, JLS không nói hành vi sẽ là gì và có thể phụ thuộc vào việc triển khai thực hiện ... trong số những thứ khác.