2010-02-23 36 views
7

Tôi cần biết các mảng đa chiều trong lớp Java mở rộng chính xác?Mảng đa chiều trong Java mở rộng lớp nào?

Khi chúng ta gán

Object[] ref=new int[]{1,2,3}; 

trình biên dịch phàn nàn rằng các đối tượng là các loại khác nhau. Vì vậy, có vẻ như một mảng một chiều mở rộng Object; Tôi biết rồi.

Nhưng khi chúng ta gán

Object[] ref2=new int[][]{{1,2,3},{4,5,6}}; 

trình biên dịch sẽ không phàn nàn. Vì vậy, có vẻ như mảng hai chiều mở rộng Object[].

Nhưng khi tôi in tên lớp cha của nó:

System.out.println(ref2.getClass().getSuperclass().getName()); 

tôi đã java.lang.Object.

Vì vậy, bất kỳ ai cũng có thể giải thích những gì đang xảy ra ở đây?

Trả lời

13

Mảng đa chiều trong Java thực sự chỉ là mảng mảng (của mảng) *.

Ngoài ra, mảng được coi là lớp con của đối tượng.

Vì vậy, int[][] của bạn là một Object[] (với thành phần loại int[]), và cũng là một Object (vì tất cả các mảng là đối tượng)

Một int[] tuy nhiên không phải là một Object[] (nhưng nó vẫn là một Object).

Vì vậy, có vẻ như hai mảng chiều mở rộng Object []

Tôi không chắc chắn nếu "mở rộng" là từ thích hợp ở đây. Mảng có một vị trí đặc biệt trong hệ thống kiểu Java và làm việc hơi khác với các đối tượng khác. Mảng hai chiều chắc chắn là một đối tượng []. Nhưng nếu bạn hỏi về superclasses, superclass duy nhất mà bất kỳ loại mảng nào có là Object. Tất cả các mảng cũng được Cloneable và Serializable.

+1

Better phrased hơn câu trả lời của tôi. +1 –

+0

@mmyers: +1 để xóa câu trả lời của bạn để ủng hộ việc đưa ra một câu trả lời mà bạn nghĩ là tốt hơn (hoặc tốt và sớm hơn). Tôi muốn nhiều người trong chúng ta làm điều đó! –

+0

Nếu chúng ta tiếp tục int [] [] [] là một đối tượng [] [], do đó, nó là một loại tính năng trong ngôn ngữ java, và không có phân cấp lớp cho các mảng. – skystar7

3

cây thừa kế của bạn trông giống như sau:

  1. ref2 là-mộtint[][]
  2. ref2 được-mộtObject[]
  3. ref2 được-mộtObject

Đây là mã đoạn minh họa những gì tôi có nghĩa là:

Object ref2 = new int[][]{{1,2,3}, {4,5,6}}; 
System.err.println("ref2: " + (ref2 instanceof int[][]) + 
    " " + (ref2 instanceof Object[])); 

Bạn sẽ thấy một cái gì đó như:

ref2: true true 
2

Mảng trong Java là hiệp biến. Điều này có nghĩa là TSub[] là một loại phụ của TSuper[] nếu TSub là một loại phụ của TSuper.

Bạn có int[][] là một mảng int[]. Bây giờ, như những người khác đã chỉ ra, bất kỳ mảng nào trong Java là một kiểu con của Object, vì vậy int[] là một kiểu con của Object. Vì vậy, do hiệp phương sai mảng, int[][] là một loại phụ của Object[] (thay thế TSub = int[]TSuper = Object trong định nghĩa hiệp phương sai ở trên).

Sửa - Để làm cho nó rõ ràng lý do tại sao hiệp phương sai là quan trọng ở đây, hãy xem xét rằng làm điều tương tự với List<T> sẽ không hoạt động:

List<Object> ref2 = new List<int[]>() 
+0

-1 lời giải thích của bạn là khó hiểu - 'int' không kế thừa trực tiếp ra' Object' – thecoop

+0

Tôi đã không nói nó đã làm - int [] (mảng int). –

1

Khi chúng ta gán

Object[] ref=new int[]{1,2,3}; 

trình biên dịch khiếu nại

Đó là vì int không phải là loại phụ của Object, int.class.getSuperclass() trả về null. Hãy nhớ rằng trong Java, các giá trị nguyên thủy (ints, longs, double, ...) không phải là các đối tượng.

Vì vậy, có vẻ như mảng hai chiều mở rộng Object [].
Nhưng khi tôi in tên lớp cha của nó:

System.out.println(ref2.getClass().getSuperclass().getName()); 

tôi đã java.lang.Object.

Mảng là giống như giao diện, khi chúng thực hiện đa kế thừa. Nhưng chúng không có giao diện thực, theo nghĩa của giao diện Java.

class A {} 
interface I {} 
class B extends A implements I {} 


B[][] bArray = new B[1][1]; 
System.out.println(bArray instanceof A[][]); 
System.out.println(bArray instanceof I[][]); 
System.out.println(bArray instanceof Object[]); 
System.out.println(bArray.getClass().getSuperclass()); 
for (Class i: bArray.getClass().getInterfaces()) 
    System.out.println(i); 
System.out.println(I[][].class.isAssignableFrom(bArray.getClass())); 
System.out.println(I[][].class.isInstance(bArray)); 

Output:

true 
true 
true 
class java.lang.Object 
interface java.lang.Cloneable 
interface java.io.Serializable 
true 
true 

Hơn nữa, Java vi phạm nguyên tắc thay thế Liskov, vì

B[] bArray = new B[1]; 
A[] aArray = bArray; 
// bArray[0] = new A(); // causes a compile error 
aArray[0] = new A(); // compiles, but causes runtime exception