4

So, I am trying to figure out why String.substring(int startIndex) allows a start index that is out of bounds and does not throw OOB exception?

Here is the code I was testing this with :

public class testSub {
public static void main(String[] args) {
    String testString = "D";
    String newSub= testString.substring(1); //print everything FROM this index Up, right? Should that not be out of bounds? Yet I just get a blank.
    System.out.println(newSub); //this works fine and prints a blank
    System.out.println(testString.charAt(1));  // <Yet this throws OOB?
    System.out.println(testString.lastIndexOf("")); // Gives me (1) but I just tried getting it? Should this not mean String length is 2?
    }
}

I understand that substrings are substring(inclusive, exclusive), but 1 is clearly out of bounds, so WHY is it giving a blank space instead of throwing OOB, or how is it doing it? Is "" some special exception?

weston
  • 54,145
  • 21
  • 145
  • 203
Kameron
  • 117
  • 1
  • 11
  • 3
    1 isn't "clearly out of bounds" - it's at the end of the string. It makes perfect sense to be able to take a 0-length substring, IMO. See http://stackoverflow.com/questions/28237907 for more reasoning on this. – Jon Skeet Feb 26 '15 at 07:23
  • its because of subString method implementation. `return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex, value);` – Prashant Feb 26 '15 at 07:24
  • 3
    In the same way that `"D".substring(0, 0)` retrieves an empty string before the first character, so does `"D".substring(1, 1)` retrieve an empty string after the last character. The behavior is symmetric. – gknicker Feb 26 '15 at 07:26
  • 2
    @gknicker: or `"".substring(0,0);` for that matter. Is that before the first or after the last ;-) – Thilo Feb 26 '15 at 07:30
  • 1
    @PacoAbato That is not a duplicate, that question is about the end index, this one is about the start index. – Mark Rotteveel Feb 26 '15 at 09:07

6 Answers6

4

As per JavaDoc, the substring method will only throw exception if index is > length of the string object. The chart method will throw exception only if index is NOT LESS than the length of the object.

Substring method(int beginIndex)

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

ChartAT Method

Returns the char value at the specified index. An index ranges from 0 to length() - 1. The first char value of the sequence is at index 0, the next at index 1, and so on, as for array indexing. If the char value specified by the index is a surrogate, the surrogate value is returned. Specified by: charAt(...) in CharSequence Parameters: index the index of the char value. Returns: the char value at the specified index of this string. The first char value is at index 0. Throws: IndexOutOfBoundsException - if the index argument is negative or not less than the length of this string. object.

Paul John
  • 1,626
  • 1
  • 13
  • 15
  • I think this answered my question best. I had read the documentation and I knew that it only throws OOB exception when larger than the length. I just did not quite understand how it could return an empty string from a call that is out of bounds. – Kameron Feb 26 '15 at 07:35
1

As the documentation say's:

 * IndexOutOfBoundsException  if
 *             <code>beginIndex</code> is negative or larger than the
 *             length of this <code>String</code> object.

Only if beginIndexis larger then length a IndexOutOfBoundsException is thrown. In your case both values are equals.

Jens
  • 67,715
  • 15
  • 98
  • 113
1

Looking at the Javadoc for String.substring(int beginIndex) for when it throws IndexOutOfBoundsException:

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

Since the String length is 1 and you are calling it with 1, you are not getting the IndexOutOfBoundsException.

mkobit
  • 43,979
  • 12
  • 156
  • 150
1

Okay people have been throwing java doc around but that doesn't really answer the question.

The reason you can do "D".substring(1) is because you're asking for the string starting at index 1, to index 1 (exclusive). This is by definition the empty string as its size is 1-1=0. Every string has an empty string at the start, end and between every character. E.g. "" + "B" + "O" + "" + "B" + "" = "BOB".

M.P. Korstanje
  • 10,426
  • 3
  • 36
  • 58
  • THIS makes sense. Thank you very much. So in essence the real String object is not just holding a simple array of characters? It has some extras. – Kameron Feb 26 '15 at 09:20
  • You're not asking the string to return its contents, you're asking the string to return another string that contains what is in the given range. This means it is true for lists and arrays too. For example `subArray( ["A","B"],2) = []`. – M.P. Korstanje Feb 26 '15 at 10:42
  • Your last comment made me completely understand. You are asking it to create a string, list etc with what is in the given range. So randomArrayList.subList(0,0) is saying "Give me a new list which has the contents of randomArrayList from index 0, up until 0,but exclusive of 0. which means, return Emptiness. – Kameron Feb 26 '15 at 12:53
0

Since your string is of length 1 and String is backed by char array, you just have char[0] populated with D as value (Note array index starts from 0 and not 1). Now you are trying to access 1st index from string (indirectly char array) using charAt method like:

System.out.println(testString.charAt(1));

And hence you get IOOB exception.

if you want to access first character from string, you should use:

System.out.println(testString.charAt(0));
SMA
  • 36,381
  • 8
  • 49
  • 73
0

What Marcio said. Plus: The method lastIndexOf is not what you think. It is the last index of the argument substring in this. For an empty string argument it will always be length plus one!

Abhay
  • 768
  • 4
  • 13