0
votes

Hello everybody and thanks in advance.

I get an error in an array line of code. I have read all threads about this and still can't handle the exception properly, causing my app force closing.

Here is my code...

    public boolean HoraErronea(String HoraAValidar) throws IndexOutOfBoundsException
{
    String HoraIntroducida = HoraAValidar;
    boolean HoraErronea = false;

    if(HoraIntroducida.length() < 3 || HoraIntroducida.length() > 5)
    {
        HoraErronea = true;
    }
    else
    {
        try
        {
            HoraIntroducida = HoraIntroducida.replace("-", ":");
            String[] HoraTroceada = HoraIntroducida.split(":");

            int hora = HoraTroceada[0].equals("")?-1:Integer.parseInt(HoraTroceada[0]);
            int minuto = HoraTroceada[1].equals("")?-1:Integer.parseInt(HoraTroceada[1]);

            if(!((hora >= 0 && hora <= 24) && (minuto >= 0 && minuto <= 59)))
            {
                HoraErronea = true;
            }
        }
        catch (IndexOutOfBoundsException e)
        {
            e.printStackTrace();
        }
    }

    return HoraErronea;
}

Ok, the thing is when "HoraIntroducida" has no ":", then "HoraTroceada[1]" doesn't exists, so my code broke throwing this message...

E/MessageQueue-JNI: java.lang.ArrayIndexOutOfBoundsException: length=1; index=1 at com.essimple.essley.FuncionesActivity.HoraErronea(FuncionesActivity.java:366) at com.essimple.essley.CalendarioActivity.ValidaDatos(CalendarioActivity.java:483) at com.essimple.essley.CalendarioActivity.onBackPressed(CalendarioActivity.java:523) at android.app.Activity.onKeyUp(Activity.java:2725) at android.view.KeyEvent.dispatch(KeyEvent.java:2699) at android.app.Activity.dispatchKeyEvent(Activity.java:3026) at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:547) at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:57) at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:315) at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:317) at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4327) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4298) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3849) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3902) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3868) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3995) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3876) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4052) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3849) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3902) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3868) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3876) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3849) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3902) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3868) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4028) at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4189) at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2365) at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1961) at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1952) at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2342) at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:323) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

I know I could check HoraTroceada's length and prevent the exception, but I'd like to do it in a better coding behaviour, catching the exception.

So please, can somebody tell me what is wrong about this?. Thank you everybody for your time and attention.

5
You don't usually handle runtime exceptions such as indexoutofBounds, you fix the causing item. - Gurwinder Singh
try to debug buddy. - Rushi Ayyappa
So, Gurwinder, if I understand you, you are telling me that better I should check length as I said before instead of handling the exception?. - Mazinger
Yes. You have to check why is the index going out of bounds in the first place (definitely a logic bug) - Gurwinder Singh
Ok, I've got it, but that's makes me wonder what are the exceptions made for then? - Mazinger

5 Answers

2
votes

To verify null reference it is necessary to use if statement:

Object ref = null;

if(ref != null) {

System.out.println(ref.toString());

}

instead of using catch statement

1
votes

Your code lacks "runtime exception handling".
See How:

 String HoraIntroducida = HoraAValidar;

Let us suppose, HoraValidar is just "1". Hence HoraIntroducida just holds "1".
Length is 1

String[] HoraTroceada = HoraIntroducida.split(":");

Since in above case, there will be just one element in HoraTroceada.

int minuto = HoraTroceada[1].equals("")?-1:Integer.parseInt(HoraTroceada[1]);

Here You are accessing element number 2 when You have just one element in your array. So expect the runtime error there.

So, solution would be

if(HoraTroceada.length == 1)
    int hora = HoraTroceada[0].equals("")?-1:Integer.parseInt(HoraTroceada[0]);
if(HoraTroceada.length == 2)
    int minuto = HoraTroceada[1].equals("")?-1:Integer.parseInt(HoraTroceada[1]);
1
votes

Based on your Exception:

java.lang.ArrayIndexOutOfBoundsException: length=1; index=1

HoraTroceada contains only one value. so that length is 1.

so we can't access "HoraTroceada[1]" this value.

So before going to do first check this character "-" is available or not like this

if(HoraIntroducida.contains("-"){
 HoraIntroducida = HoraIntroducida.replace("-", ":");
String[] HoraTroceada = HoraIntroducida.split(":");
}

It should be help full.

0
votes

Before accessing the index , check the length of the array if it's greater than 0 then access the index

if(HoraTroceada.length > 0){
    int hora = HoraTroceada[0].equals("")?-1:Integer.parseInt(HoraTroceada[0]);
        int minuto = HoraTroceada[1].equals("")?-1:Integer.parseInt(HoraTroceada[1]);
}
0
votes

As the other answers have suggested you are improperly using the array indices. You should always test to see if the returned object is what you expected. In your case you are expecting an array of size 2. Then make this check explicit and handle the error situation correctly.

Generally speaking you should always be checking the outputs of the methods you call. You should handle the inconsistencies appropriately like throwing an exception or displaying an error message. Check that the returned object is:

  • not NULL
  • not in the specific range you are looking for
  • not empty
  • is of the right type

If inconsistency is detected, then throw an exception and quit early from your method. Otherwise you are risking passing invalid data to deeper parts of your code which can lead to data corruption and undefined behaviour.

You can find more tips at handling exceptions in my article: Exceptions Guidelines