Why does this lead to an ArrayIndexOutOfBoundsException?

There is something that doesn't quite make sense to me. Why does this:

public static int[] countNumbers(String n){
int[] counts = new int[10];

for (int i = 0; i < n.length(); i++){
    if (Character.isDigit(n.charAt(i)))
        counts[n.charAt(i)]++;
}
return counts;
}

bring up an ArrayOutOfBounds error while this:

  public static int[] countNumbers(String n){
    int[] counts = new int[10];

    for (int i = 0; i < n.length(); i++){
        if (Character.isDigit(n.charAt(i)))
            counts[n.charAt(i) - '0']++;
    }
    return counts;
    }

does not? The only difference between the two examples is that the index for counts is being subtracted by zero in the second example. If I'm not mistake, shouldn't the first example display correctly since the same value is being checked?

Here are the value being passed for the two methods:

System.out.print("Enter a string: ");
String phone = input.nextLine();

//Array that invokes the count letter method
int[] letters = countLetters(phone.toLowerCase());

//Array that invokes the count number method
int[] numbers = countNumbers(phone);
Jon Skeet
people
quotationmark

This is the problem:

 counts[n.charAt(i)]++;

n.charAt(i) is a character, which will be converted to an integer. So '0' is actually 48, for example... but your array only has 10 elements.

Note that the working version isn't subtracting 0 - it's subtracting '0', or 48 when converted to an int.

So basically:

Character          UTF-16 code unit        UTF-16 code unit - '0'
'0'                48                      0
'1'                49                      1
'2'                50                      2
'3'                51                      3
'4'                52                      4
'5'                53                      5
'6'                54                      6
'7'                55                      7
'8'                56                      8
'9'                67                      9

The code is still broken for non-ASCII digits though. As it can only handle ASCII digits, it would be better to make that explicit:

for (int i = 0; i < n.length(); i++){
    char c = n.charAt(i);
    if (c >= '0' && c <= '9') {
        counts[c - '0']++;
    }
}

people

See more on this question at Stackoverflow