charAt()

Reads the single char at a zero-based index, and throws StringIndexOutOfBoundsException when the index is outside the String.

Signature
public char charAt(int index)
  • Added in Java Java 1.0

Parameters

ParameterTypeDescription
$indexintZero-based position, from 0 to length() - 1.

Return value

charThe char value at the given index. The first char is at index 0.

Errors

IndexOutOfBoundsException (thrown as StringIndexOutOfBoundsException) if index is negative or not less than length().

charAt(i) returns the char at position i. Indexes start at 0, so the first char is s.charAt(0) and the last is s.charAt(s.length() - 1). Anything outside that range throws StringIndexOutOfBoundsException, which is a subclass of IndexOutOfBoundsException.

The empty String trap

s.charAt(0) on an empty String throws. Input from a query parameter, a CSV cell or a header can be empty, so check isEmpty() before reading the first char, or use startsWith, which simply returns false.

char is a number

A char is an unsigned 16-bit integer. That is useful: c - '0' turns the digit '7' into the int 7, and c >= 'a' && c <= 'z' tests for a lowercase ASCII letter. It also surprises people: c + 1 is an int, so printing it shows a number, and you need a cast to get a char back. Likewise "" + c1 + c2 joins two chars, but c1 + c2 adds them.

One char is not always one character

An emoji is stored as two chars, a high and a low surrogate. charAt returns just one half, which is not a printable character on its own. If the text can contain any Unicode, use codePointAt(i) and step forward with Character.charCount(cp), or use codePoints().

When to use it

Reach for charAt in small hand-written parsers and validators: checking a token alphabet, computing a check digit, or scanning a path for separators. It is fast, does not allocate, and the JIT compiler handles it well in a tight loop. For searching, indexOf is clearer; for anything pattern-shaped, a precompiled regular expression is easier to read. Avoid Character.isLetterOrDigit when you mean ASCII only, because it accepts letters from every script.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Validating that a request ID header uses only letters, digits and hyphens.
  • Checking the check digit of a card or account number before calling a payment API.
  • Reading the first char of a sort parameter to tell '-createdAt' (descending) from 'createdAt'.

Frequently asked questions

How do I get the last character of a String in Java?

Use s.charAt(s.length() - 1), after checking that s is not empty. On an empty String that index is -1 and the call throws StringIndexOutOfBoundsException.

How do I convert a digit char to an int?

Subtract '0': '7' - '0' is 7. Character.getNumericValue(c) also works and handles digits from other scripts, while Character.digit(c, 16) parses hexadecimal digits.

More examples

Checking a token alphabet

Explicit ASCII ranges reject the accented letter, which Character.isLetterOrDigit would accept. That difference matters for request IDs or keys that end up in URLs, file names or log searches.

Example · java
boolean isToken(String s) {
    if (s.isEmpty()) return false;
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        boolean ok = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
                || (c >= '0' && c <= '9') || c == '-';
        if (!ok) return false;
    }
    return true;
}

void main() {
    for (String s : List.of("req-7f3a", "req 7f3a", "", "abc\u00e9")) {
        IO.println("\"" + s + "\" " + isToken(s));
    }
}
// Output:
// "req-7f3a" true
// "req 7f3a" false
// "" false
// "abcé" false

Computing a Luhn check digit

Subtracting '0' turns a digit char into its numeric value without parsing. Card numbers and many reference numbers use this check, so a payment form can reject a typo before calling the provider.

Example · java
boolean luhn(String digits) {
    int sum = 0;
    boolean twice = false;
    for (int i = digits.length() - 1; i >= 0; i--) {
        int d = digits.charAt(i) - '0';   // '7' - '0' is 7
        if (twice) {
            d *= 2;
            if (d > 9) d -= 9;
        }
        sum += d;
        twice = !twice;
    }
    return sum % 10 == 0;
}

void main() {
    IO.println(luhn("79927398713"));
    IO.println(luhn("79927398710"));
}
// Output:
// true
// false

charAt and characters outside the BMP

charAt(0) returns only the high surrogate of the emoji, while codePointAt(0) combines both halves into the real code point. The exclamation mark sits at index 2 because the emoji occupies two chars.

Example · java
void main() {
    String s = "\uD83D\uDE00!";
    char first = s.charAt(0);
    IO.println(Character.isHighSurrogate(first));
    IO.println(Integer.toHexString(first));

    int cp = s.codePointAt(0);
    IO.println(Integer.toHexString(cp));
    IO.println(Character.toString(cp));
    IO.println(s.charAt(2));        // the emoji used indexes 0 and 1
}
// Output:
// true
// d83d
// 1f600
// 😀
// !

Discussion

  • Be the first to comment on this lesson.