2010-07-13 30 views
16

Trong Java, tôi đang sử dụng phương thức substring() và tôi không chắc tại sao nó không ném lỗi "hết chỉ mục".Tại sao "ngoài phạm vi" không được ném cho 'chuỗi con (startIndex, endIndex)'

Chuỗi abcde có chỉ mục bắt đầu từ 0 đến 4, nhưng phương pháp substring() lấy startIndex và endIndex làm đối số dựa trên thực tế là tôi có thể gọi foo.substring (0) và nhận "abcde".

Sau đó, tại sao chuỗi con (5) hoạt động? Chỉ mục đó phải nằm ngoài phạm vi. Giải thích là gì?

/* 
1234 
abcde 
*/ 
String foo = "abcde"; 
System.out.println(foo.substring(0)); 
System.out.println(foo.substring(1)); 
System.out.println(foo.substring(2)); 
System.out.println(foo.substring(3)); 
System.out.println(foo.substring(4)); 
System.out.println(foo.substring(5)); 

Mã này kết quả đầu ra:

abcde 
bcde 
cde 
de 
e 
    //foo.substring(5) output nothing here, isn't this out of range? 

Khi tôi thay thế 5 với 6:

foo.substring(6) 

Sau đó, tôi nhận được lỗi:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: 
    String index out of range: -1 

Trả lời

18

Theo Java API doc, chuỗi con ném một lỗi khi chỉ số bắt đầu lớn hơn Chiều dài của String.

IndexOutOfBoundsException - if beginIndex is negative or larger than the length of this String object.

Trong thực tế, họ đưa ra một ví dụ giống như bạn:

"emptiness".substring(9) returns "" (an empty string) 

Tôi đoán điều này có nghĩa nó là tốt nhất để nghĩ về một String Java như sau, nơi một chỉ số được bọc trong |:

|0| A |1| B |2| C |3| D |4| E |5| 

Để nói chuỗi có cả chỉ mục bắt đầu và kết thúc.

+0

Ahh! cảm ơn những người đầu, tôi đã nhìn vào cùng một trang tài liệu nhưng không biết tôi đã phải cuộn xuống tất cả các cách để có thêm chi tiết ... –

+4

Chúc các javadoc có thể có một lưu ý về điều này, hoặc những kẻ bất cẩn như tôi sẽ mong đợi 'IndexOutOfBoundsException' xảy ra nếu beginIndex = String.length(). –

2

substring (5) điểm một chỉ mục hiện có ... nó chỉ xảy ra để trỏ đến một sản phẩm nào chuỗi. chuỗi con (6), mặt khác, chỉ là nói chuyện điên rồ. :)

14

Khi bạn làm foo.substring(5), nó sẽ nhận chuỗi con bắt đầu từ vị trí ngay sau "e" và kết thúc ở cuối chuỗi. Ngẫu nhiên, vị trí bắt đầu và kết thúc xảy ra giống nhau. Vì vậy, chuỗi rỗng. Bạn có thể nghĩ rằng chỉ mục không phải là một ký tự thực trong chuỗi, mà là một vị trí giữa các ký tự.

 --------------------- 
String: | a | b | c | d | e | 
     --------------------- 
Index: 0 1 2 3 4 5 
3

Từ Chuỗi API javadoc:

public String substring(int beginIndex) 
    Returns a new string that is a substring of this 
    string. The substring begins with the "" character 
    at the specified index and extends to the end of this string. 

public String substring(int beginIndex, int endIndex) 
    Returns a new string that is a substring of this 
    string. The substring begins at the specified beginIndex 
    and extends to the character at index endIndex - 1. Thus 
    the length of the substring is endIndex-beginIndex. 

Ví dụ:

"unhappy".substring(2) returns "happy" 
"Harbison".substring(3) returns "bison" 
"emptiness".substring(9) returns "" (an empty string) 

"hamburger".substring(4, 8) returns "urge" 
"smiles".substring(1, 5) returns "mile" 

Tham số:

beginIndex - the beginning index, inclusive. 
Returns: 
the specified substring. 
Throws: 
IndexOutOfBoundsException - if beginIndex is negative or 
larger than the length of this String object. 

====

Vì vậy, đây là theo thiết kế. Nếu bạn cung cấp cho chỉ mục là kích thước của chuỗi, nó sẽ trả về chuỗi rỗng.

3

Tôi biết chủ đề này là khá cũ nhưng đây là một vấn đề cơ bản mà tôi nghĩ rằng nó đảm bảo làm rõ.

Câu hỏi đặt đúng vị trí. Tôi xem đây là lỗi phần mềm trong phương thức Java String.substring (int beginIndex, int endIndex).

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring%28int,%20int%29.

Từ Java Documents https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

Java Arrays

Java/C/C++ và mọi ngôn ngữ khác mà tôi biết KHÔNG xem các chỉ số mảng như là 'chia' giữa các phần tử mảng.

Tham số: beginIndex - chỉ mục bắt đầu, bao gồm. endIndex - chỉ mục kết thúc, độc quyền.

Hoặc là endIndex bị đặt tên sai vì ngôn ngữ không cho phép truy cập bộ nhớ vào địa chỉ ở endIndex + 1 được yêu cầu bao gồm phần tử mảng cuối HOẶC endIndex bị định nghĩa sai và phải là: endIndex - chỉ mục kết thúc, bao gồm .

Trường hợp nhiều khả năng nhất là thông số thứ hai bị đặt tên sai. Nó phải là: chiều dài - độ dài của chuỗi bắt đầu mong muốn tại beginIndex.

Chúng tôi biết rằng Gosling dựa trên cú pháp Java trên ngôn ngữ C/C++ để làm quen. Từ lớp C + + + http://www.cplusplus.com/reference/string/string/substr/, chúng tôi thấy định nghĩa phương thức là:

chất nền chuỗi (size_t pos = 0, size_t len ​​= npos) const;

Lưu ý rằng tham số thứ hai trong định nghĩa phương thức là 'len' cho chiều dài.

len Số ký tự để bao gồm trong chuỗi con (nếu chuỗi ngắn hơn, nhiều ký tự nhất có thể được sử dụng).

testString có 10 ký tự, vị trí chỉ mục từ 0 đến 9. Chỉ định endIndex là 10 nên luôn ném chỉ mục IndexOutOfBoundsException() vì testString không có endIndex là 10.

Nếu chúng tôi thử nghiệm phương pháp này trong JUnit với các giá trị cụ thể xem xét phương pháp C++, chúng tôi mong đợi:

Chuỗi testString = "testString"; assertThat (testString.substring (4, 6), equalTo ("String"));

nhưng tất nhiên chúng tôi được dự kiến: "String" nhưng là "St"

Chiều dài của testString từ chỉ số từ 0 đến char 'g' trong 'String' là 10 ký tự. Nếu chúng tôi sử dụng 10 làm thông số 'endIndex',

Chuỗi testString = "testString"; assertThat (testString.substring (4, 10), equalTo ("String"));

"Vượt qua" từ JUnit.

Nếu đổi tên tham số 2 thành "lengthOfSubstringFromIndex0", bạn không phải thực hiện đếm endIndex - 1 và nó không bao giờ ném chỉ số IndexOutOfBoundsException() được mong đợi khi chỉ định một endIndex, 10, nằm ngoài phạm vi cho mảng cơ bản. http://docs.oracle.com/javase/7/docs/api/java/lang/IndexOutOfBoundsException.html

Đây chỉ là một trong những thời điểm mà bạn phải nhớ sự riêng tư của phương pháp này. Tham số thứ hai không được đặt tên chính xác. Chữ ký của phương thức Java phải là:

public String substring(int beginIndex, 
      int lengthOfSubstringFromIndex0) 

Hoặc phương pháp được xác định lại để khớp với chuỗi C++ :: phương thức substr. Việc định nghĩa lại tất nhiên sẽ có nghĩa là viết lại toàn bộ internet, vì vậy nó không có khả năng.

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