Làm thế nào để xem một đối tượng là một mảng mà không sử dụng phản xạ?


98

Làm thế nào tôi có thể xem trong Java nếu một Đối tượng là một mảng mà không sử dụng phản chiếu? Và làm cách nào để tôi có thể lặp lại tất cả các mục mà không cần sử dụng phản chiếu?

Tôi sử dụng Google GWT nên tôi không được phép sử dụng phản chiếu :(

Tôi rất thích triển khai các phương pháp sau mà không cần sử dụng tính năng lọc lại:

private boolean isArray(final Object obj) {
  //??..
}

private String toString(final Object arrayObject) {
  //??..
}

BTW: Tôi cũng không muốn sử dụng JavaScript để tôi có thể sử dụng nó trong các môi trường không phải GWT.

Câu trả lời:


247

Bạn có thể dùng Class.isArray()

public static boolean isArray(Object obj)
{
    return obj!=null && obj.getClass().isArray();
}

Điều này hoạt động cho cả mảng đối tượng và mảng kiểu nguyên thủy.

Đối với toString, hãy xem Arrays.toString. Bạn sẽ phải kiểm tra kiểu mảng và gọi toStringphương thức thích hợp .


1
Đáng thêm rằng bạn có thể tìm ra kiểu mảng bằng cách sử dụng obj.getClass().getComponentType().
Steve Chambers

68

Bạn có thể sử dụng instanceof.

Toán tử so sánh loại JLS 15.20.2 instanceof

 RelationalExpression:
    RelationalExpression instanceof ReferenceType

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

Điều đó có nghĩa là bạn có thể làm điều gì đó như sau:

Object o = new int[] { 1,2 };
System.out.println(o instanceof int[]); // prints "true"        

Bạn sẽ phải kiểm tra xem đối tượng là một instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], hoặc Object[], nếu bạn muốn để phát hiện tất cả các loại mảng.

Ngoài ra, an int[][]là một instanceof Object[], vì vậy tùy thuộc vào cách bạn muốn xử lý các mảng lồng nhau, nó có thể trở nên phức tạp.

Đối với toString, java.util.Arrayscó một toString(int[])và các quá tải khác mà bạn có thể sử dụng. Nó cũng có deepToString(Object[])cho các mảng lồng nhau.

public String toString(Object arr) {
   if (arr instanceof int[]) {
      return Arrays.toString((int[]) arr);
   } else //...
}

Nó sẽ rất lặp lại (nhưng thậm chí java.util.Arrayslà rất lặp lại ), nhưng đó là cách nó xảy ra trong Java với mảng.

Xem thêm


Cảm ơn, nó không nhận ra nó đơn giản như vậy. T [] :(
edbras

2
BTW: Tôi cũng nhận thấy một cách hay khác để khám phá xem thứ gì đó có phải là một mảng Class.isArray () (được sử dụng trong Arrays.deepToString ()) hay không.
edbras

@edbras: vâng, đó là những gì Steve Kuo đã nói bên dưới. Giải pháp của tôi sử dụng cấu trúc ngôn ngữ thuần túy thay vì lệnh gọi API.
polygenelubricants

Nó hoạt động tốt, tôi chỉ không sử dụng instanceof mà là getClass để so sánh. Một cái gì đó như: if (array.getClass == int []. Class) {Arrays.toString ((int []) array); } Cảm ơn tất cả ..
edbras

@edbras: Đó là cách java.util.Arraysthực hiện, vâng. Tôi thấy rằng bạn đang đọc mã mà tôi liên kết đến.
polygenelubricants

35

Người ta có thể truy cập từng phần tử của một mảng riêng biệt bằng cách sử dụng mã sau:

Object o=...;
if ( o.getClass().isArray() ) {
    for(int i=0; i<Array.getLength(o); i++){
        System.out.println(Array.get(o, i));
    }
}

Lưu ý rằng không cần thiết phải biết nó là loại mảng cơ bản nào, vì điều này sẽ hoạt động với bất kỳ mảng nào.


2
isArray()đã được đề cập đầy đủ trong các câu trả lời được đăng 4 năm trước câu trả lời này.
Jason C

15
Câu trả lời này rất hay vì nó chỉ cho chúng ta cách lấy kích thước của một mảng và truy xuất một phần tử mà không cần biết về kiểu nội dung của nó. Tôi chắc rằng hầu hết mọi người chưa bao giờ viết mã như thế này trước đây.
Christopher Yang,

@MaartenBodewes - Tôi sẽ sử dụng liên kết này để quyết định "không sử dụng phản chiếu" có nghĩa là gì đối với GWT.
Stephen C

10

Không có mối quan hệ kiểu con giữa các mảng kiểu nguyên thủy hoặc giữa mảng kiểu nguyên thủy và mảng kiểu tham chiếu. Xem JLS 4.10.3 .

Do đó, cách kiểm tra sau đây không chính xác để xem liệu objcó phải là một mảng thuộc bất kỳ loại nào hay không :

// INCORRECT!
public boolean isArray(final Object obj) {
    return obj instanceof Object[];
}

Cụ thể, nó không hoạt động nếu objlà mảng 1-D của các nguyên thủy. (Tuy nhiên, nó hoạt động đối với các mảng nguyên thủy có kích thước cao hơn, bởi vì tất cả các kiểu mảng đều là kiểu con của Object. Nhưng trong trường hợp này thì rất khó.)

Tôi sử dụng Google GWT nên tôi không được phép sử dụng phản chiếu :(

Giải pháp tốt nhất (cho phần isArraymảng của câu hỏi) phụ thuộc vào điều gì được coi là "sử dụng phản xạ".

  • Trong GWT, việc gọi obj.getClass().isArray()không được tính là sử dụng phản xạ 1 , vì vậy đó là giải pháp tốt nhất.

  • Nếu không, cách tốt nhất để tìm xem một đối tượng có kiểu mảng hay không là sử dụng một chuỗi instanceofbiểu thức.

    public boolean isArray(final Object obj) {
        return obj instanceof Object[] || obj instanceof boolean[] ||
           obj instanceof byte[] || obj instanceof short[] ||
           obj instanceof char[] || obj instanceof int[] ||
           obj instanceof long[] || obj instanceof float[] ||
           obj instanceof double[];
    }
  • Bạn cũng có thể thử làm lộn xộn với tên của lớp của đối tượng như sau, nhưng lệnh gọi đến obj.getClass()giáp với phản chiếu.

    public boolean isArray(final Object obj) {
        return obj.getClass().toString().charAt(0) == '[';
    }

1 - Chính xác hơn, Class.isArrayphương pháp này được GWT hỗ trợ trong trang này .


0

Bạn có thể tạo một lớp tiện ích để kiểm tra xem lớp đó có đại diện cho Bộ sưu tập , Bản đồ hoặc Mảng nào không

  public static boolean isCollection(Class<?> rawPropertyType) {
        return Collection.class.isAssignableFrom(rawPropertyType) || 
               Map.class.isAssignableFrom(rawPropertyType) || 
               rawPropertyType.isArray();
 }

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.