Baba rencho
Baba rencho

Reputation: 29

Java array with substring - String index out of range exception

How to handle exception with String index out of range? I was interviewed and asked the following question like below.

I have the following program below:

        String currentUserFirstName = "raj";
        String currentUserLastName = "ar";


        String strFoo[] = new String[]{
           (currentUserLastName.substring(0, 3)+"."+currentUserFirstName),
           (currentUserFirstName+"."+currentUserLastName.substring(0, 1))
        };


    for(int i=0; i<strFoo.length; i++){
        System.out.println(strFoo[i]);  
    }

I am getting the following output:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
    at java.lang.String.substring(Unknown Source)

I want to get the following output below:

Exception
raj.a

I want to handle exception inside loop if value's length is not sufficient to substring.

Help would be appreciated!

EDITED I tried using below:

for(int i=0; i<strFoo.length; i++){
    try{            
       System.out.println(strFoo[i]);   
    }catch(Exception e){System.out.println("Exception");}
}

But it doesn't work!

Upvotes: 0

Views: 2565

Answers (4)

DevilsHnd - 退した
DevilsHnd - 退した

Reputation: 9192

Before using the String.substring() method there are a couple of conditions you need to consider so as not to encounter an exception when the code is run. First of course is if either string variable contains Null or a Null String (""); Second would be the length of string contained within the variable where the .substring() method will be worked against, does it have the adequate index level (length) for the number of characters you want to retrieve?

Now knowing the different conditions that could fault your code and or output, you need to decide what you want to do when these specific conditions occur.

As an example, let's say that currentUserLastName actually contains a Null String (""). Do you what to ignore the variable and not work the .substring() method against it so that you would end up with raj. or would you rather pad the blank section with something like perhaps a hash mark (#) so that you end up with something like" raj.###. Perhaps it would be better to simply inform a User that a last name is required and not run the code block at all.

The same applies to variables that contain a string length that does not meet your index requirement for the number of characters you want to retrieve from the string contained within. If you want to retrieve 3 characters from the last name but the last name only contains 2, what do you want to do with the third slot? Ignore it and only utilize the two characters that are available: raj.ar or pad it and fill the third slot with perhaps a Hash Mark (#) or perhaps a simple whitespace: raj.ar#. You can't very well demand a User to change their last name so that it has at least 3 characters.

The example code below demonstrates how you might handle the above mentioned fault conditions. Of course it is naturally assumed that the variables currentUserFirstName and currentUserLastName would naturally acquire there strings by some other means other than hard coded but for the sake of this example we will simply use what you have provided:

String currentUserFirstName = "raj";
String currentUserLastName = "ar";

// Make sure our variables contain data.
if (currentUserFirstName.isEmpty() || currentUserLastName.isEmpty()) { 
    // Display an error message to console if one does not.
    System.err.println("ERROR! Both the First and Last name must contain something!\n"
                     + "First Name: " + currentUserFirstName + "\n"
                     + "Last Name : " + currentUserLastName);
}
else {
    // Declare and initialize the strgFoo[] Array
    String strFoo[] = new String[2];
    // Does currentUserLastName contain at least 3 characters?
    if(currentUserLastName.length() >= 3) {
        // Yes it does...
        strFoo[0] = currentUserLastName.substring(0, 3)+"."+currentUserFirstName;
    }
    else {
        // No it doesn't so let's use the string length
        // inside currentUserLastName to determine our
        // required index for the .substring() method.
        strFoo[0] = currentUserLastName.substring(0, currentUserLastName.length()) + 
                    "." + currentUserFirstName;
    }
    // Fill in the second element for our Array
    strFoo[1] = currentUserFirstName+"." + currentUserLastName.substring(0, 1);

    // Iterate through the Array and
    // display its contents to Console.
    for(int i = 0; i < strFoo.length; i++){
        System.out.println(strFoo[i]);  
    }
}

Upvotes: 1

Honza Zidek
Honza Zidek

Reputation: 20036

You should shift your attention from exception handling to a more general design of your code.

It is generally a very bad practice to control your algorithm with exceptions. It is like instead of looking around before crossing the street, you just jump there and if you are hit with a car, you now start considering the possibility that there might have been some traffic.

Instead, query the length of the strings which you work with:

if (currentUserFirstName.length() >= 3) {
    currentUserLastName.substring(0, 3)...
} else {
    // something else, based on the fact that the string is not long enough
}

Upvotes: 0

user2862544
user2862544

Reputation: 425

StringIndexOutOfBoundsException is not getting thrown from loop. exception is coming from here : currentUserLastName.substring(0, 3)

it happening because last name length is two and you are passing 0 to 3 , it should be 0 to 2 only . subString method throws exception if: - if the beginIndex is negative, or endIndex is larger than the length of this String object, or beginIndex is larger than endIndex.

hence in substring we can pass 0 to currentUserLastName.length()

Upvotes: 0

Max
Max

Reputation: 1345

An important note is that the error is being caused by the fact that you are trying to get characters between 0 and 3. But

0 - "r",

1 - "a",

2 - "j",

3 - There's no character here, but you're trying to access it, so an exception is thrown.

You're putting your try/catch in the wrong place.

Checking the length of the string first (better)

To get the length of a string, one can access its .length() method, which takes no arguments. If it's greater than 3, execute the code, but otherwise don't.

if(currentUserFirstName.length() > 3) {
    // your substring code
    // then your for loop
} else {
    // error handling
}

This is probably cleaner, since silencing an exception isn't always a good idea.

Using a try/catch statement (worse)

This is what you attempted to do in your question. Just move it up a little bit, around the substring attempt.

try{
    String strFoo[] = new String[]{
       (currentUserLastName.substring(0, 3)+"."+currentUserFirstName),
       (currentUserFirstName+"."+currentUserLastName.substring(0, 1))
    };

    /* then either
         a) put your for-loop here
         b) mark a variable as true here, and check after the entire try/catch to see if you should run the loop
       neither is good. Best use the If/Else approach
    */
} catch(Exception e) { 
    System.out.println("Exception");
}

This will work, but resorting to try/catch isn't needed in this case, and using one anyway could mean that if you have another error in the same piece of code, it'll be silently hidden and your code will react as if you're substring is out of range.

Since your for-loop at the end relies on everything succeeding, you have to make sure nothing failed before continuing. The best way to do this would be switching to the if/else method (and putting your for-loop in the "if" part). If you don't want to do this, you can either put your code in the "try" section (but if you have some other problem in your for-loop, your code will assume it's because of the substring problem); or mark a variable as true, or false, depending on whether the code entered the catch phase, and then put your for-loop in an if-statement, but this is, again sloppy.

The best way, in my opinion, is, as I mentioned, using the if/else approach. It's very rarely clean code to use a try/catch to handle these issues.

Upvotes: 0

Related Questions