Java String Index Out Of Bounds Exception

gmanrocks :

Yes I know how to fix this. I was looking at the API between String Class and String Builder Class. Here's what I question:

StringBuilder sb = new StringBuilder("wibble");
String s = new String("wobble");

sb.charAt(index) //Can throw Index Out Of Bounds Exception
s.charAt(index) //Can throw Index Out of Bounds Exception

sb.substring(start, end) //Can throw STRING index out of bounds exception
s.substring(start, end) //Only throws Index out of Bounds Exception (no String)

So what doesn't make sense is when it decides to throw a StringIndexOutOfBoundsException vs an IndexOutOfBoundsException. Yes I know StringIndex is a sub exception. In both String and StringBuilder, some methods that have the same implementation throw the same exception, while in some methods that have the same implementation, StringBuilder throws the sub exception. So why is that?

To save people scrolling through the answers and thanks to the 2 people who answered even though I can only select one as answered, both helped clarify: Java Oracle Doc People made a typo in substring for String. It is supposed to be StringIndexOutOfBoundsException. Same with CharAt() in StringBuilder

Tim Klein :

This comes down to which JDK implementation you are using.

I did some digging and found the implemented method, public char charAt(int index) for the StringBuilder class. (Note: I am using Oracle JDK 1.8).

So, in this case, the StringBuilder class is a subclass of AbstractStringBuilder. This is a choice of the implementing programmer as you won't find this in the docs.

I found the charAt function was implemented on the AbstractStringBuilder base class. Here are some screenshots of the code in question, from my system. (Remember, specific JDK is Oracle & Java 1.8).

enter image description here

enter image description here

Update

I actually ran some code to test what exceptions are thrown and found something interesting. The charAt() function in my environment also throws a java.lang.StringIndexOutOfBoundsException. Here is the code I ran to test it:

public class StringVsStringBuilder {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("one");
        String string = "two";

        try {
            builder.charAt(10); // Clearly out of bounds
        } catch (IndexOutOfBoundsException e) {
            System.out.println(String.format(
                    "Exception encountered accessing character out of index bounds on variable 'builder': %s",
                    e.getClass()
            ));
        }

        try {
            string.charAt(10); // Clearly out of bounds
        } catch (IndexOutOfBoundsException e) {
            System.out.println(String.format(
                    "Exception encountered accessing character out of index bounds on variable 'string': %s",
                    e.getClass()
            ));
        }
    }
}

And here is the output when run (Windows 10, 64bit, Oracle JDK 1.8.0_191):

Exception encountered accessing character out of index bounds on variable 'builder': class java.lang.StringIndexOutOfBoundsException
Exception encountered accessing character out of index bounds on variable 'string': class java.lang.StringIndexOutOfBoundsException

Process finished with exit code 0

To address some questions from the comments:

  • [AbstractStringBuilder] isn't in the docs which means we can't write programs with it?

    One usually follows the other. The AbstractStringBuilder class is private to the java.lang package, meaning that it cannot be access from outside of that package. This means that you would not be able to import and use this class in your code. This is a perfect example of some portion of code that is not part of the public API of the system (in this case, the JDK itself), in which case, it will not be documented, for several reasons:

    1. You cannot use it
    2. Implementation details could potentially change constantly
    3. It should not affect the use of the public API (the documented portion of the system)
  • if charAt() in StringBuilder throws a StringIndexOutOfBoundsException, then why does the docs say simply IndexOutOfBoundsException?

    This is because that is the described behavior of the charAt() function based on the design intent of the class. Since you can create any number of sub-classes for exceptions (just like any other Java class that is not final) then it is always up to the implementing programmer to choose what it best to return (or throw) from a function, as long as the function adheres to the agreed upon contract (interface, doc spec, abstract class, etc.).

    Having said that, you could implement the JDK right now and choose your own subclass of IndexOutOfBoundsException to throw in this scenario. If I were to use StringBuilder.charAt() in my code, I would catch the exception that is described in the docs, because that would allow me the most flexibility/portability without risking breaks from reliance on implementation details. Entire books have been written on this topic, so I will leave the discussion here: always try to catch the most specific exception that you know could be thrown, meaning, if it is possible that other implementations may not throw StringOutOfBoundsException, then you better be catching just IndexOutOfBoundsException since it is guaranteed to be of that type (or a subclass of it).

Update 2

In this specific case, you can pretty much ignore everything I mentioned above and just focus on the following:

charAt() is an interface method described in java.lang.CharSequence. This means that for any implementing class, the issue raised when an index out of the bounds of the sequence is attempted to be accessed will be an IndexOutOfBoundsException. The interface describes general behavior and it is not necessary for this behavior to be defined in terms of a String, a StringBuilder, an AlphabetSoup or any other specific implementation. If those impls. decide to subclass that exception and give more specific error info in each case, that is fine, but it does not change the general contract. If you are writing a generic character processing system, then you will likely write to the interface and not care about the underlying impl. In which case, you will only know (or care) about IndexOutOfBoundsException and nothing else.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=81826&siteId=1