2012-10-06 60 views
15
public class RefMix { 
    public static void main(String[] args) { 
    Object[] a = {null, "foo"}; 
    Object[] b = {"bar", b}; 
    a[0] = b; 

    System.out.println(a[0][0]); 
    } 
} 

Hiểu biết của tôi là mảng là đối tượng trong Java và do đó là lớp con của loại đối tượng. Sự hiểu biết thêm của tôi là một mảng 2-dim được thực hiện như một mảng các tham chiếu đến các mảng. Vì vậy, tôi không hiểu tại sao [0] [0] của tôi không sản xuất bar trong mã ở trên. Thay vào đó, nó không biên dịch:Loại đối tượng trong Java và mảng tham chiếu

RefMix.java:7: array required, but java.lang.Object found 

Trả lời

13

Hiểu biết của tôi là mảng là đối tượng trong Java và do đó là lớp con của loại Đối tượng. Sự hiểu biết thêm của tôi là một mảng 2-dim được thực hiện như một mảng các tham chiếu đến các mảng.

Đây là tất cả đúng và giải thích lý do tại sao bạn có thể làm nhiệm vụ

a[0] = b; 

mà không cần bất kỳ khiếu nại từ các trình biên dịch.

Vì vậy, tôi không hiểu tại sao [0] [0] không sản xuất thanh trong mã ở trên.

Được rồi, chúng ta hãy nhìn vào các loại trong biểu thức này:

  • a là một Object[] - đó là một mảng của Object s
  • a[0] là một Object
  • a[0][0] - - Bây giờ bạn đang cố gắng sử dụng một chỉ số mảng trên một Object. Trình biên dịch không biết rằng Object là trong thực tế một mảng, do đó, nó than phiền.
10

Loại thời gian chạy của thể hiện đối tượng khác với loại suy luận tĩnh. Trình biên dịch sẽ cố gắng ước tính loại biến nào có thể có trong chương trình, để bắt các loại lỗi nhất định sớm. Trong trường hợp này, a[0] sẽ luôn là một mảng, nhưng trình biên dịch không biết điều này. Vì bạn đang lấy một đối tượng ra khỏi một mảng đối tượng, tất cả trình biên dịch biết là a[0] là một đối tượng. Do đó nó làm tăng một lỗi.

Trong trường hợp bạn biết điều gì đó luôn luôn là một loại nhất định nhưng trình biên dịch không thể tìm ra, bạn có thể giải quyết vấn đề này bằng cách chèn một diễn viên rõ ràng.

System.out.println(((Object[])a[0])[0]); 
+0

Sự xấu xí của một diễn viên như thế này đã truyền cảm hứng cho tôi từ bỏ việc sử dụng các mảng như thế này; Tôi sẽ chỉ sử dụng lớp tham chiếu đối tượng "bình thường". Nhưng cảm ơn! – Fixee

+3

@Fixee, mảng trong Java là khá xấu xí, nhưng bạn thường có thể tránh sự cần thiết cho phôi bằng cách giảm số lần bạn lưu trữ dữ liệu không đồng nhất. Bạn thường không cần lưu trữ cả chuỗi và đối tượng [] s trong cùng một mảng. – Antimony

+2

@Antimony Tôi thực sự không thể tìm thấy một trường hợp sử dụng duy nhất mà bạn sẽ * cần * một thứ như vậy ...;) – brimborium

4

Kể từ mảng trong Java là một đối tượng, vì vậy 1 và nhiệm vụ thứ 2, sẽ lưu trữ mảng của bạn là yếu tố 1 của mảng Object của bạn ..

Object[] a = {null, "foo"}; 
Object[] b = {"bar", b}; 

Bây giờ, bạn đã thay đổi 1 của bạn phần tử của a mảng đối tượng để chứa giá trị b thay vì mảng .. Nhưng vì nó là một mảng đối tượng. Tất cả mọi thứ ra khỏi nó sẽ là đối tượng ..

Kể từ a [0] là một đối tượng .. Vì vậy, bạn rõ ràng không thể truy cập vào một cái gì đó như thế này: -

System.out.println(a[0][0]); 

Bạn có thể thử để định kiểu đối tượng của bạn một [0] để đối tượng mảng ..: -

System.out.println(((Object[])a[0])[0]); 
4

Đỗ:

System.out.println(((Object[])a[0])[0]); 

này sẽ "đúc" đối tượng vào một mảng đối tượng trong thời gian chạy.

7

Bạn nói đúng, mảng luôn Objects trong Java, nhưng Objects không phải lúc nào các mảng, do đó bạn nhận được một lỗi biên dịch, vì a là một Object[] (một chiều). Bạn không thể truy cập

a[0][0]; 

a không phải là một mảng hai chiều (ít nhất là nó không tuyên bố như vậy). Tuy nhiên, trong trường hợp này, bạn chắc chắn rằng, a[0] là một mảng của Objects. Do đó, bạn có thể làm điều này:

Object[] c = (Object[]) a[0]; 
System.out.println(c[0]); 
// or directly: 
System.out.println(((Object[])a[0])[0]); 

này phôi kiểu trả về của a[0] (đó là Object), vào một Object[] và sau đó bạn có thể truy cập vào "lớp thứ hai" của mảng.

1

Tất cả những gì bạn đang làm là tương đương với này

Object a = {"bar", "foo"}; 
System.out.println(a[0]); 

mà không biên dịch một trong hai.

2

Như tôi đã làm rất nhiều mã C++ gần đây, tôi thấy rằng Java là rất nhiều nghiêm ngặt hơn trong kiểm tra kiểu thì C++ là. Java thấy mọi thứ trừ các kiểu nguyên thủy như Object nhưng Java đi thêm một bước nữa trong việc phân biệt các kiểu Array và non-Array. Trong quá trình gán như "a [0] = b;" , Java đầu tiên kiểm tra xem nó có phải là một loại mảng hay không, sau đó nó đi qua thủ tục kiểm tra kiểu đa hình thông thường. Nếu bạn muốn làm cho công việc mã của bạn, bạn nên làm ...

Object[][] a = {{null}, {"foo"}}; 
Object[] b = {"bar", new java.util.Date()}; 
a[0] = b; 

Bạn có thể xem như thế nào java chăm sóc đặc biệt đối với các loại mảng bằng cách nhìn vào Java Class chữ ký sẽ được chuyển cho Class.forName() như tham số . Ví dụ, kiểu dữ liệu ..

com.foo.Bar[][] barsIn2D; 

có thể được nạp với chữ ký dưới đây ...

// [ => Array 
// [[ => Array of Array type 
// L<object>; => Object, not Array 
Class.forName("[[Lcom/foo/Bar;"); 

Như bạn thấy, chữ ký bắt đầu với một trong hai '[' hoặc 'L'. Điều này cho chúng ta biết một mảng của nó hay không được ưu tiên hơn "Lcom/foo/Bar;".

Các vấn đề liên quan