Phản chiếu mảng Java: isArray so với instanceof


177

Có sự khác biệt về sở thích hoặc hành vi giữa việc sử dụng:

if(obj.getClass().isArray()) {}

if(obj instanceof Object[]) {}

?

Câu trả lời:


203

Trong hầu hết các trường hợp, bạn nên sử dụng instanceoftoán tử để kiểm tra xem một đối tượng có phải là một mảng hay không.

Nói chung, bạn kiểm tra loại đối tượng trước khi chuyển sang loại cụ thể được biết đến tại thời điểm biên dịch. Ví dụ, có lẽ bạn đã viết một số mã có thể làm việc với một Integer[]hoặc một int[]. Bạn muốn bảo vệ dàn diễn viên của mình với instanceof:

if (obj instanceof Integer[]) {
    Integer[] array = (Integer[]) obj;
    /* Use the boxed array */
} else if (obj instanceof int[]) {
    int[] array = (int[]) obj;
    /* Use the primitive array */
} else ...

Ở mức JVM, instanceoftoán tử chuyển thành mã byte "instanceof" cụ thể , được tối ưu hóa trong hầu hết các triển khai JVM.

Trong các trường hợp hiếm hơn, bạn có thể sử dụng sự phản chiếu để duyệt qua biểu đồ đối tượng của các loại không xác định. Trong những trường hợp như thế này, isArray()phương pháp có thể hữu ích vì bạn không biết loại thành phần tại thời điểm biên dịch; ví dụ, bạn có thể thực hiện một số loại cơ chế tuần tự hóa và có thể truyền từng thành phần của mảng cho cùng một phương thức tuần tự hóa, bất kể loại nào.

Có hai trường hợp đặc biệt: tham chiếu null và tham chiếu đến mảng nguyên thủy.

Một tham chiếu null sẽ gây ra instanceofkết quả false, trong khi isArrayném a NullPointerException.

Áp dụng cho một mảng nguyên thủy, instanceofsản lượng falsetrừ khi loại thành phần trên toán hạng bên phải khớp chính xác với loại thành phần. Ngược lại, isArray()sẽ trả về truecho bất kỳ loại thành phần.


7
Vâng, nhưng nó sẽ tạo ra bao nhiêu sự khác biệt? Nghe có vẻ như là một tối ưu hóa vi mô đối với tôi.
Michael Myers

2
@Dims Nếu bạn đang khẳng định rằng obj instanceof int[]mang lại lợi nhuận falsekhi bạn gán int[]cho obj, bạn đã nhầm.
erickson

4
Xin lỗi tôi có nghĩa là obj instanceof Object[]năng suất falsenếu Object obj = new int[7].
dims

3
Đúng, trong Java, các kiểu dữ liệu nguyên thủy không phải là đối tượng và không mở rộng java.lang.Object, vì vậy điều đó có ý nghĩa. Nhưng instanceofvẫn có thể được sử dụng để kiểm tra các mảng nguyên thủy.
erickson

4
-1: Nói chung, vì các mảng nguyên thủy các mảng gọi isArray()nên được sử dụng. Trong trường hợp không đặc biệt chung là chỉ có mảng các đối tượng, instanceofcung cấp một sự thay thế hiệu suất cao.
Sam Harwell

33

Trong trường hợp sau, nếu obj là null, bạn sẽ không nhận được NullPulumException nhưng sai.


8

Nếu objlà kiểu int[]nói, thì nó sẽ có một mảng Classnhưng không phải là một thể hiện của Object[]. Vậy bạn muốn làm gì với obj. Nếu bạn sẽ đúc nó, đi với instanceof. Nếu bạn sẽ sử dụng sự phản chiếu, sau đó sử dụng .getClass().isArray().


4

getClass().isArray() chậm hơn đáng kể trên Sun Java 5 hoặc 6 JRE so với trên IBM.

Quá nhiều việc sử dụng clazz.getName().charAt(0) == '['nhanh hơn trên Sun JVM.


10
Bạn có bất kỳ số liệu thống kê, nghiên cứu trường hợp, hoặc bằng chứng khác mà bạn có thể liên kết đến?
David Citron

4

Gần đây tôi đã gặp phải một vấn đề khi nâng cấp ứng dụng Groovy từ JDK 5 lên JDK 6. Sử dụng isArray()thất bại trong JDK6:

MissingMethodException:
No signature of sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl.isArray() ...

Thay đổi để instanceof Object[]sửa lỗi này.


Điều này không có ý nghĩa. isArraylà một phương pháp Class, không Type, vì vậy tất nhiên GenericArrayTypeImplkhông có phương pháp đó. Và getClasskhông bao giờ có thể trả lại một người không Class Type, vì vậy bạn (hoặc Groovy ??) phải làm điều gì đó sai để có được điều này, như giả sử mọi thứ Typelà a Class.
kaqqao

3

Phản chiếu mảng Java dành cho các trường hợp bạn không có phiên bản Class có sẵn để thực hiện "instanceof". Ví dụ: nếu bạn đang viết một số khung công tác tiêm, tiêm các giá trị vào một thể hiện mới của một lớp, chẳng hạn như JPA, thì bạn cần sử dụng chức năng isArray ().

Tôi viết blog về điều này sớm hơn vào tháng 12. http://blog.adamsbros.org/2010/12/08/java-array-reflection/


2

Nếu bạn có lựa chọn giữa giải pháp phản chiếu và giải pháp không phản chiếu, không bao giờ chọn giải pháp phản chiếu (liên quan đến các đối tượng Class). Không phải là "Sai" hay bất cứ điều gì, nhưng bất cứ điều gì liên quan đến sự phản chiếu thường không rõ ràng và ít rõ ràng hơn.


Er, tốt, "instanceof" là một loại hình phản chiếu (hoặc, ít nhất là, hướng nội) là tốt, nhưng tôi hiểu quan điểm của bạn.
David Citron

Ngoài ra, nó thường chậm hơn.
Nhà vật lý điên

0

Không có sự khác biệt trong hành vi mà tôi có thể tìm thấy giữa hai người (trừ trường hợp null rõ ràng). Đối với phiên bản nào thích hơn, tôi sẽ đi với phiên bản thứ hai. Đây là cách tiêu chuẩn để làm điều này trong Java.

Nếu nó gây nhầm lẫn cho người đọc mã của bạn (vì String[] instanceof Object[]là đúng), bạn có thể muốn sử dụng mã đầu tiên để rõ ràng hơn nếu người đánh giá mã tiếp tục hỏi về mã đó.

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.