Là kiểm tra null cần thiết trước khi gọi instanceof?


1354

Sẽ null instanceof SomeClasstrở lại falsehoặc ném một NullPointerException?


Nó cũng 'quan trọng' hoặc ít nhất là rất hữu ích như là một dòng 'bắt đầu thực hành tốt nhất' (hoặc rất sớm) cho bất kỳ phương pháp So sánh hoặc Bằng hoặc tương tự nào được thiết kế để chỉ thành công trên các đối tượng không cùng loại và bảo vệ bạn chống lại 'các trường hợp ngớ ngẩn' trong một dòng duy nhất. ít mã hơn = ít lỗi hơn

13
Để cân nhắc về "điều này có hữu ích không?" tranh luận - Tôi chưa bao giờ viết mã Java của riêng mình (vì vậy không dễ dàng biết được thông số kỹ thuật ở đâu và việc biên dịch một bài kiểm tra sẽ không tầm thường), nhưng hiện tại tôi đang chuyển đổi thủ công Java sang JavaScript. Mã của tôi đã thất bại trong một tham chiếu null và việc tìm kiếm nó cho tôi xem câu trả lời được chấp nhận, điều này đã xác nhận rằng đó là hành vi được mong đợi và tôi đã bỏ lỡ một kiểm tra null ẩn. Rất hữu ích, trong trường hợp của tôi.
Scott Mermelstein

Câu trả lời:


1839

Không, không cần kiểm tra null trước khi sử dụng instanceof.

Biểu thức x instanceof SomeClassfalsenếu xnull .

Từ Đặc tả ngôn ngữ Java, phần 15.20.2, "Thể hiện toán tử so sánh kiểu" :

"Trong thời gian chạy, kết quả của instanceoftoán tử là truenếu giá trị của RelationalExpression khôngnull và tham chiếu có thể được chuyển sang ReferenceType mà không tăng a ClassCastException. Nếu không thì kết quả là false."

Vì vậy, nếu toán hạng là null, kết quả là sai.


377
Câu trả lời này đúng hơn try ithành vi hiện tại không giống với hành vi được đảm bảo .
Lu-ca

3
Câu hỏi này xuất hiện trong chương của Joshua Bloch về sự bình đẳng đối tượng trong Effective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
Kevin Meredith

17
Cụ thể, trong Mục 8, ông lưu ý rằng trong các phương thức equals (), một toán tử instanceof phục vụ hai mục đích - nó xác minh rằng đối số là không null và đúng loại. "... [S] o bạn không cần kiểm tra null riêng biệt."
Andy Thomas

2
@BenThurley - instanceofToán tử của Java là một phần của Java 1.0, được phát hành gần 20 năm trước. Thay đổi hành vi bây giờ theo cách có thể phá vỡ mã hiện tại là không thể, vắng mặt một số lợi ích vượt xa chi phí khổng lồ đó. Hai mươi năm trước, có thể đã có những cuộc tranh luận để trả lại sự thật nếu cuộc tranh luận có thể được đưa ra, hoặc đưa ra một ngoại lệ cho một cuộc tranh luận không có giá trị. Nhưng những định nghĩa đó sẽ yêu cầu kiểm tra null riêng biệt.
Andy Thomas

3
@BenThurley - Hành vi được đảm bảo bởi các đặc tả Java trong quá khứ và hiện tại. Tôi nghĩ rằng quan điểm của Luke giải quyết các hạn chế của thử nghiệm trong việc xác định hành vi được bảo đảm của hiện tại.
Andy Thomas

267

Sử dụng một tham chiếu null làm toán hạng đầu tiên để instanceoftrả về false.


268
(Và bây giờ phải mất 10 giây để tìm câu hỏi này trong Google)
PL_kolek

73

Câu hỏi rất hay thực sự. Tôi chỉ cố gắng cho bản thân mình.

public class IsInstanceOfTest {

    public static void main(final String[] args) {

        String s;

        s = "";

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));

        s = null;

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));
    }
}

Bản in

true
true
false
false

JLS / 15.20.2. Kiểu toán tử so sánh

Trong thời gian chạy, kết quả của instanceoftoán tử là truenếu giá trị của RelationalExpression không nullvà tham chiếu có thể được chuyển sang ReferenceType mà không tăng a ClassCastException. Nếu không thì kết quả là false.

API / Class # isInstance (Object)

Nếu Classđối tượng này đại diện cho một giao diện, phương thức này trả về truenếu lớp hoặc bất kỳ siêu lớp nào của Objectđối số đã chỉ định thực hiện giao diện này; nó trả falsekhác. Nếu Classđối tượng này đại diện cho một kiểu nguyên thủy, phương thức này trả về false.


Loại khó hiểu. s là một Chuỗi vì nó nói "Chuỗi s", s không phải là Chuỗi vì nó là null. Vậy cái quái gì là s?
Kai Wang

1
@KaiWang schỉ là một biến tham chiếu đối tượng. Nó có thể đề cập đến một đối tượng thực sự tồn tại ( "") hoặc nó có thể đề cập đến một (các) nulltham chiếu theo nghĩa đen.
Jin Kwon

Tôi vẫn còn bối rối. Bây giờ có thể là null, nhưng nó chỉ có thể được trỏ đến một thể hiện String sau đó. Nó không thể được trỏ đến, như, một Integer. Vì vậy, nó vẫn là một chuỗi, thậm chí nó là null. Chỉ là không có ý nghĩa nhiều ...
Kai Wang

@KaiWang Bạn đang nhầm lẫn loại biến với loại đối tượng thực tế. Biến không phải là trường hợp; họ thực sự chỉ là con trỏ. nullkhông phải là dữ liệu chuỗi, bất kể biến nào đang trỏ đến nó. s instanceof Stringkhông giống như field.getType().equals(String.class), ví dụ.
Matthew đọc

@KaiWang bạn phải tưởng tượng rằng trong cuộc gọi s instanceof String, sđược thay thế bằng giá trị thực, do đó, nó sẽ trở thành "" instanceof Stringnull instanceof String. Suy nghĩ về nó như thế này có thể có ý nghĩa hơn.
Timo Türschmann

24

Không, không phải vậy. instanceofsẽ trở lại falsenếu toán hạng đầu tiên của nó là null.


16

Cũng như một miếng ngon :

Thậm chí sẽ trở lại .(((A)null)instanceof A)false


(Nếu typecasting nullcó vẻ đáng ngạc nhiên, đôi khi bạn phải làm điều đó, ví dụ trong các tình huống như thế này:

public class Test
{
  public static void test(A a)
  {
    System.out.println("a instanceof A: " + (a instanceof A));
  }

  public static void test(B b) {
    // Overloaded version. Would cause reference ambiguity (compile error)
    // if Test.test(null) was called without casting.
    // So you need to call Test.test((A)null) or Test.test((B)null).
  }
}

Vì vậy, Test.test((A)null)sẽ in a instanceof A: false.)


Tái bút: Nếu bạn đang tuyển dụng, xin đừng sử dụng nó như một câu hỏi phỏng vấn xin việc. : D


7

Không . Chữ Java nullkhông phải là một thể hiện của bất kỳ lớp nào. Vì vậy, nó không thể là một thể hiện của bất kỳ lớp nào. instanceof sẽ trả về một trong hai falsehoặctrue do đó <referenceVariable> instanceof <SomeClass>trả về falsekhi referenceVariablegiá trị là null.


5
Lời giải thích đó nghe có vẻ kỳ lạ ... nhưng tôi hiểu ý của bạn là :-)
Kris

@Kris ty cho ý kiến ​​Tôi hiểu ý bạn :). Chỉnh sửa một câu trả lời một chút :).
Nhà phát triển Marius ilėnas

1

Các instanceofnhà điều hành không cần rõ ràng nullséc, vì nó không ném một NullPointerExceptionnếu toán hạng lànull .

Trong thời gian chạy, kết quả của instanceoftoán tử là đúng nếu giá trị của biểu thức quan hệ khôngnull và tham chiếu có thể được chuyển sang loại tham chiếu mà không đưa ra ngoại lệ truyền lớp.

Nếu toán hạng là null, instanceoftoán tử trả vềfalse và do đó, kiểm tra null rõ ràng là không bắt buộc.

Hãy xem xét ví dụ dưới đây,

public static void main(String[] args) {
         if(lista != null && lista instanceof ArrayList) {                     //Violation
                System.out.println("In if block");
         }
         else {
                System.out.println("In else block");
         }
}

Cách sử dụng đúng instanceoflà như dưới đây,

public static void main(String[] args) {
      
         if(lista instanceof ArrayList){                     //Correct way
                  System.out.println("In if block");
         }
            else {
                 System.out.println("In else block");
         }  
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.