Tại sao Java cho phép các mảng có kích thước 0?


82

Mảng trong java có độ dài cố định. Tại sao Java lại cho phép các mảng có kích thước 0?

String[] strings = new String[0];

Câu trả lời:


122

Nó có nghĩa là nó trống rỗng. Tức là bạn có thể lặp lại nó như thể nó có các mục và không có kết quả nào xảy ra:

for(int k = 0; k < strings.length; k++){
   // something
}

Qua đó tránh được việc phải kiểm tra. Nếu mảng được đề cập null, một ngoại lệ sẽ xảy ra, nhưng trong trường hợp này, nó không làm gì cả, điều này có thể phù hợp.


9
Nó cũng hữu ích cho gọi một chức năng test(Object... objects)rõ ràng khi có một chức năngtest()
Frithjof

51

Tại sao Java cho phép các mảng có kích thước 1? Không phải là khá vô ích khi bao bọc một giá trị trong một mảng? Sẽ không đủ nếu Java chỉ cho phép các mảng có kích thước 2 hoặc lớn hơn?

Vâng, chúng tôi có thể vượt qua null thay vì một mảng trống và một đối tượng hoặc nguyên thủy thay vì một ma trận kích thước một.

Nhưng có một số lập luận tốt chống lại một hạn chế như vậy. Đối số hàng đầu của cá nhân tôi:

Hạn chế quá phức tạp và không thực sự cần thiết

Để giới hạn mảng ở kích thước [1..INTEGER.MAX_INT], chúng tôi sẽ phải thêm nhiều kiểm tra boudary bổ sung, (đồng ý với nhận xét của Konrads) logic chuyển đổi và quá tải phương thức đối với mã của chúng tôi. Loại trừ 0 (và có thể là 1) khỏi kích thước mảng cho phép không tiết kiệm chi phí, nó đòi hỏi nỗ lực bổ sung và có tác động tiêu cực đến hiệu suất.

Mô hình mảng vector

Một mảng là một mô hình dữ liệu tốt cho một vector (toán học, không những Vectorlớp!). Và tất nhiên, một vectơ trong toán học có thể là không chiều. Đó là khái niệm khác với không tồn tại.


Sidenote - một trình bao bọc nổi bật cho mảng (char-) là Stringlớp. Immutable hiện Stringthực hóa khái niệm về một mảng trống: nó là String ( "") rỗng .


2
Tôi không tin lập luận hạn chế của bạn. Java (không giống như C) đã yêu cầu kiểm tra các số âm. Kiểm tra này có thể được điều chỉnh một cách đáng kể để có vị trí 0 (chỉ cần thay đổi >= 0thành > 0). Nhưng tất nhiên bạn đã đúng về phần còn lại nên việc thêm phần hạn chế này sẽ không có ý nghĩa.
Konrad Rudolph

Đối số lặp vòng lặp có vẻ tốt hơn theo ý kiến ​​của tôi: "for (int k = 0; k <string.length; k ++) {// something}"
dannyxyz22

2
Không, theo ý kiến của tôi thì không, bởi vì trong một thế giới không có mảng kích thước bằng 0, các chuỗi rỗng (dựa trên mảng char) đơn giản là sẽ không tồn tại và vì vậy không cần xem xét các mảng trống trong vòng lặp. Lập luận lặp lại này là một tác dụng phụ rất thực tế. Trong thế giới đó, một mảng sẽ có ít nhất một mục nhập. (Hoặc hai vì: tại sao một cần một mảng chỉ một mục?)
Andreas Dolk

Vui lòng cung cho một chỉ số tiêu cực và một chỉ số quá cao là việc kiểm tra như nhau: chỉ số tiêu cực luôn unsigned-không-ít-hơn độ dài của mảng
harold

26

Đôi khi trả về mảng kích thước bằng 0 sẽ thân thiện hơn nhiều so với giá trị null.


9
Đây được gọi là mẫu "Null Object".
Aleksandr Dubinsky

16

Hãy xem xét điều này (giải thích chi tiết hơn về câu trả lời của Noon):

public String[] getStrings() {
 if( foo ) {
  return null;
 } else {
  return new String[] {"bar, "baz"};
 }
}

String[] strings = getStrings();
if (strings != null) {
 for (String s : strings) {
  blah(s);
 }
}

Bây giờ hãy so sánh nó với cái này:

public String[] getStrings() {
 if( foo ) {
  return new String[0];
 } else {
  return new String[] {"bar, "baz"};
 }
}

// the if block is not necessary anymore
String[] strings = getStrings();
for (String s : strings) {
 blah(s);
}

Điều này (trả về mảng trống chứ không phải giá trị rỗng), trên thực tế là một phương pháp hay nhất trong thế giới thiết kế API Java.

Bên cạnh đó, trong Java, bạn có thể ẩn Danh sách (ví dụ: ArrayList) thành các mảng và việc chuyển đổi một danh sách trống thành một mảng trống chỉ có ý nghĩa.


5

Giống như C ++, nó cho phép xử lý sạch hơn khi không có dữ liệu.


4

Một trường hợp khác mà mảng có độ dài bằng 0 có thể hữu ích: Để trả về một mảng chứa tất cả các phần tử trong danh sách:

<T> T[ ] toArray(T[ ] a)

Một mảng có độ dài bằng 0 có thể được sử dụng để truyền kiểu của mảng vào phương thức này. Ví dụ:

ClassA[ ] result = list.toArray(new ClassA[0]);

Mảng có độ dài bằng không vẫn là một thể hiện của Đối tượng chứa không phần tử.


2

Một trường hợp mà tôi có thể nghĩ đến khi một mảng trống cực kỳ hữu ích là sử dụng nó thay vì null trong trường hợp không cho phép null. Một ví dụ có thể về điều đó là BlockingQueue của mảng. Khi bạn muốn báo hiệu kết thúc đầu vào cho phía đọc, bạn sẽ làm gì? Gửi null có vẻ như là một lựa chọn hiển nhiên, nhưng vấn đề là BlockingQueue không chấp nhận null. Bạn có thể bao bọc mảng của mình bên trong một lớp với boolean last;loại trường "", nhưng đó là loại trường quá mức cần thiết. Gửi một mảng trống (có kích thước bằng 0) có vẻ là lựa chọn hợp lý nhất.


0

Một trường hợp khác khi mảng có độ dài bằng 0 rất hữu ích là khi sao chép một mảng hai chiều. Tôi có thể viết:

public int[][] copyArray(int[][] array){
     int[][] newArray = new int[array.length][0];
     for(int i=0;i<array.length;i++){
         newArray[i] = array[i];
     }
     return newArray;

Do mọi tham chiếu mảng trong mảng đang bị ghi đè, nên việc khởi tạo chúng dưới dạng các mảng có độ dài bằng không là hiệu quả nhất.


0

Độ dài 0 byte[]hoặc char[]có thể biểu thị giá trị trống String, khác với null. Lấy các byte hoặc ký tự dưới dạng mảng từ chuỗi (sử dụng getBytes(), getChars()thuộc Stringlớp, v.v.) và ngược lại khi tạo thành Stringtừ s byte[], char[]khá phổ biến. Ví dụ, đối với mã hóa tùy chỉnh, giải mã các chuỗi.

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.