Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does char not autobox to Character in Java?

Tags:

java

Working to improve ESAPI's encoding methods to handle non-BMP characters, I encountered unexpected behavior. It was interesting, to say the least...

This unit test:

public void testCSSEncodeChar0x100()
{
    char in = 0x100;
    String inStr = Character.toString(in);
    String expected = "\\100 ";
    String result;

        result = cssCodec.encodeCharacter(EMPTY_CHAR_ARRAY, in);
    // this should be escaped
        assertFalse(inStr.equals(result));
        assertEquals(expected,result);
}

I had in my mind--only one target method. I have two methods:

@Override
public String encodeCharacter( char[] immune, Character c ) {
    return ""+c;
}

@Override
public String encodeCharacter( char[] immune, int codePoint ) {
    return new StringBuilder().appendCodePoint(codePoint).toString();
}

I would have expected Java to autobox the variable in to a Character, but instead, it got upcast to an int and ended up calling the second method.

Tried Google, didn't get any answers on this non-intuitive behavior.

As to what worked, simply changing the type of in from char to Character resolved the problem.

like image 927
avgvstvs Avatar asked Jan 29 '23 21:01

avgvstvs


1 Answers

Java can box char to Character perfectly easily. This will work fine:

Character c = in;

However, overload resolution occurs in multiple phases for the sake of backwards compatibility. In early versions of Java (before autoboxing) your second method would already have been applicable (as there's always been a widening conversion from char to int) but the first method wouldn't have been... so it's the second method that's picked.

When you change the type of in from char to Character, only the first method is applicable, so that's used instead.

JLS 15.12.2 contains the details:

The remainder of the process is split into three phases, to ensure compatibility with versions of the Java programming language prior to Java SE 5.0. The phases are:

  • The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase. [...]

  • The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase. [...]

  • The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

like image 187
Jon Skeet Avatar answered Feb 02 '23 10:02

Jon Skeet