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.
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.
See more on this question at Stackoverflow