2010-07-13 8 views
16

In Java verwende ich die substring() Methode und ich bin mir nicht sicher, warum es keinen Fehler "out of index" wirft.Warum wird "out of range" nicht für 'substring (startIndex, endIndex)'

Der String abcde hat den Index Start 0-4, aber die substring() Methode nimmt start und endIndex als Argument auf der Tatsache, dass ich foo.substring nennen kann (0) und „ABCDE“ erhalten.

Warum funktioniert Teilzeichenfolge (5)? Dieser Index sollte außerhalb des zulässigen Bereichs liegen. Was ist die Erklärung?

/* 
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)); 

Dieser Code gibt:

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

Wenn ich 5 mit 6 ersetzen:

foo.substring(6) 

Dann bekomme ich Fehler:

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

Antwort

18

Nach den Java API doc, wirft Teilzeichenfolge einen Fehler, wenn der Startindex größer ist als die Länge ist des String.

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

In der Tat, sie geben ein Beispiel ähnlich wie bei Ihnen:

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

Ich denke, das bedeutet, dass es am besten ist, einen Java-String als Folgendes zu denken, wo ein Index in | gewickelt ist:

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

Das heißt, ein String hat sowohl einen Start- als auch einen Endindex.

+0

Ahh! Danke für die Tipp-Leute, ich schaute auf die gleiche Doc-Seite, wusste aber nicht, dass ich den ganzen Weg runterscrollen musste, um mehr Details zu bekommen ... –

+4

Wünschte, dass der Javadoc eine Notiz darüber haben kann, oder unvorsichtige Typen wie ich werden expect 'IndexOutOfBoundsException' ist aufgetreten, wenn beginIndex = String.length(). –

2

substring (5) Punkte ein existierender Index ... es zeigt einfach auf ein leeres Zeichenfolge. Teilstring (6) ist dagegen nur ein verrücktes Gesprächsthema. :)

14

Wenn Sie foo.substring(5) tun, erhält es die Teilzeichenfolge beginnend an der Position direkt nach dem "e" und endet am Ende der Zeichenfolge. Die Start- und Endposition sind übrigens gleich. Also, leere Zeichenfolge. Sie können sich den Index nicht als ein tatsächliches Zeichen in der Zeichenfolge, sondern als eine Position zwischen Zeichen vorstellen.

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

Von String 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. 

Beispiele:

"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" 

Parameter:

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

Dies wird in der Dokumentation gezeigt

====

Das ist also von Entwurf. Wenn Sie den Index als die Größe der Zeichenfolge angeben, wird eine leere Zeichenfolge zurückgegeben.

3

Ich weiß, dass dieser Thread ziemlich alt ist, aber das ist solch ein grundlegendes Problem, dass ich denke, dass es Klärung rechtfertigt.

Die Frage ist genau richtig. Ich sehe dies als Softwarefehler in der Methode Java String Substring (int beginIndex, int endIndex).

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

Vom Java Docs https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

Java Arrays

Java/C/C++ und jede andere Sprache, die ich kenne, ist nicht der Array-Index als 'Teiler' zwischen Arrayelementen anzuzeigen.

Parameter: beginIndex - der Anfangsindex, inklusive. endIndex - der Endungsindex, exklusiv.

Entweder endIndex ist falsch benannt, weil die Sprache keinen Speicherzugriff auf die Adresse am endIndex + 1 zulässt, die erforderlich ist, um das letzte Arrayelement einzubeziehen ODER endIndex ist falsch definiert und muss sein: endIndex - der Endindex, einschließlich .

Der wahrscheinlichste Fall ist, dass der zweite Parameter falsch benannt wurde. Es sollte sein: length - die Länge der gewünschten Zeichenfolge beginnend am beginIndex.

Wir wissen, dass Gosling die Java-Syntax auf die C/C++ - Sprachen für Vertrautheit basiert. Von C+++ String Klasse http://www.cplusplus.com/reference/string/string/substr/ sehen wir die Methodendefinition ist:

Zeichenfolge substr (Größe_tpos = 0, size_t len ​​= npos) const;

Beachten Sie, dass der zweite Parameter in der Methodendefinition für die Länge 'len' ist.

len Anzahl der Zeichen, die im Teilstring enthalten sein sollen (wenn der String kürzer ist, werden so viele Zeichen wie möglich verwendet).

testString hat 10 Zeichen, Indexpositionen 0 bis 9. Das Angeben eines endIndex von 10 sollte immer die IndexOutOfBoundsException() auslösen, da testString keinen endIndex von 10 hat.

Wenn wir die Methode in JUnit mit konkreten Werten Blick auf die C++ Methode zu testen, erwarten wir:

String teststring = "teststring"; assertThat (testString.string (4, 6), equalTo ("String"));

aber natürlich werden wir voraussichtlich erhalten: "String" war aber "St"

Die Länge der aus dem Index 0 teststring 'g' in 'String' char ist 10 Zeichen. Wenn wir 10 als 'endIndex' Parameter verwenden,

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

"Pass" von JUnit.

Wenn wir Parameter 2 in "lengthOfSubstringFromIndex0" umbenennen, müssen Sie die endIndex-1-Zählung nicht ausführen, und es wird niemals die IndexOutOfBoundsException() ausgelöst, die bei der Angabe eines endIndex, 10, außerhalb des Bereichs für das zugrunde liegende Array. http://docs.oracle.com/javase/7/docs/api/java/lang/IndexOutOfBoundsException.html

Dies ist nur eine dieser Zeiten, dass Sie die Idiosynkrasie dieser Methode erinnern müssen. Der zweite Parameter wird nicht korrekt benannt. Die Java-Methodensignatur sollte wie folgt lauten:

Oder die Methode neu definiert, um C++ string :: substr-Methode zu entsprechen. Neudefinition würde natürlich bedeuten, das gesamte Internet neu zu schreiben, also ist es nicht wahrscheinlich.

Verwandte Themen