javaeventsjavafxkeyeventevent-driven

Why KeyEvent getCharacter returns a string not a character


Based on my understanding, the getCharacter() method of KeyEvent should return a char type.

For example, if I have to check if the typed key is a digit, I can just use Character.isDigit(e.getCharacter()) not Character.isDigit(e.getCharacter().charAt(0)).

I also checked the length of the returned string by printing e.getCharacter().length() it always returns 1. Any explanation or other usage of this string?


Solution

  • KeyEvent#getCharacter() returns String

    Based on my understanding, the getCharacter() method of KeyEvent should return a char type.

    From where did you get that understanding? The Javadoc for javafx.scene.input.KeyEvent#getCharacter() says that method returns a String object reference, not a char primitive.

    Avoid char

    Understand that char is a legacy type, essentially broken since Java 2, legacy since Java 5. As a 16-bit value, a char is physically incapable of representing most of the 149,186 characters defined in Unicode.

    Code points

    Instead use code point integer numbers to work with individual characters.

    int[] codePoints = myKeyEvent.getCharacter().codePoints().toArray() ;
    

    You can then interrogate if any of those code points represents a digit.

    boolean isDigit = Character.isDigit( myCodePoint ) ;
    

    Example code

    String input = "A1😷";  // FACE WITH MEDICAL MASK  is hex 1F637, decimal 128,567.
    
    System.out.println( "input.length(): " + input.length() ) ;  
    System.out.println( "Count code points: " + input.codePoints().count() + "\n" ) ;
      
    input.codePoints ( ).forEach (
            ( int codePoint ) ->
            {
                System.out.println (
                        "Code point: " + codePoint +
                                " | name: " + Character.getName ( codePoint ) +
                                " | digit: " + Character.isDigit ( codePoint ) +
                                " | = " + Character.toString ( codePoint ) +
                                "\n- - - - - - - - - - - - - - - - - - - - "
                );
            }
    );
    

    See this code run at Ideone.com.

    input.length(): 4
    Count code points: 3
    
    Code point: 65 | name: LATIN CAPITAL LETTER A | digit: false | = A
    - - - - - - - - - - - - - - - - - - - - 
    Code point: 49 | name: DIGIT ONE | digit: true | = 1
    - - - - - - - - - - - - - - - - - - - - 
    Code point: 128567 | name: FACE WITH MEDICAL MASK | digit: false | = 😷
    - - - - - - - - - - - - - - - - - - - - 
    

    You said:

    I can just use Character.isDigit(e.getCharacter())

    No, you cannot. The isDigit method takes either a legacy char or a modern code point int. The getCharacter method returns neither of those; that method returns a String as discussed above.


    For background info, see the surprisingly entertaining article: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) by Joel Spolsky.