2

In Java, I find the following code much cleaner and easier to maintain than the corresponding bulky switch statement:

try {
  selectedObj = new Object[] {
    objA,
    objB,
    objC,
    objD,
  }[unvalidatedIndex];
} catch (ArrayIndexOutOfBoundsException e) {
  selectedObj = objA;
}

opposed to

switch (unvalidatedIndex) {
  case 0:
    selectedObj = objA;
    break;

  case 1:
    selectedObj = objB;
    break;

  case 2:
    selectedObj = objC;
    break;

  case 3:
    selectedObj = objD;
    break;

  default:
    selectedObj = objA;
}

Is the former considered an acceptable practice? I am aware that it's not the most efficient one as it involves allocating an array and catching an exception. Would it cause something undesirable when unvalidatedIndex is out of range (although the exception is handled)?

If possible, would you suggest something cleaner?

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130

6 Answers6

5

Your first approach is fine.

However, it is better to check the index first:

Object[] arr = new Object[] { ... };

if (i < 0 || i >= arr.length)
    i = 0;
selectedObj = arr[i];
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Nice, but that pollutes the namespace with an additional identifier `arr` that's used just once. On the other hand, `arr.length` can be substituted with the constant `4` if an anonymous array is used, but that incurs a maintenance cost of always keeping this constant and the array in sync. I know I sound picky, but I'm asking this out of curiosity. – Blagovest Buyukliev Jun 06 '11 at 14:18
  • 1
    @Blagovest: Wrap it in `{ }` to make an inner scope and hide the variable. Or make a `static` function that takes an index and an `Object...` and returns an object. – SLaks Jun 06 '11 at 14:23
2

It is not an acceptable practice. Exceptions are for errors handling, not for program flow. Also exceptions are VERY SLOW.

bigGuy
  • 1,732
  • 1
  • 22
  • 37
1

How about

if(index < arr.length && index >= 0){
    obj = arr[index];
}else{
    obj = defaultValue;
}
javanna
  • 59,145
  • 14
  • 144
  • 125
jmj
  • 237,923
  • 42
  • 401
  • 438
1

Both are antipatterns. Just test the index for range membership yourself. There might be a way to use an enum in many actual cases.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
user207421
  • 305,947
  • 44
  • 307
  • 483
1

Personally, though I have no doubt some will disagree, I would do:

switch (unvalidatedIndex) {
    case 0 : selectedObj = objA; break;
    case 1 : selectedObj = objB; break;
    case 2 : selectedObj = objC; break;
    case 3 : selectedObj = objD; break;
    default: selectedObj = objA; break;
    }

It's clean, compact, efficient, and really easy to understand.

I would hesitate to include the case 0, that being the default case.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
-1
    int index = 4;

    ArrayList<String> myObjects = Lists.newArrayList("a", "b", "c", "d");
    Object o = index  < myObjects.size() && index >= 0 ? myObjects.get(index) : null;
    System.out.println(o);

Lists comes from Guava.

Peeter
  • 9,282
  • 5
  • 36
  • 53