A method in class Test<T>
which returns an integer....
public int getIndex(T a) //generic parameter
{
return 1; // purposely left simple
}
An array instantiated with default size 5: boolean[] arr = new boolean[5];
now I have a couple of overloading function, purposely made simple....
public void add(T a) // generic parameter
{
add(getIndex(a));
}
public void add(int a)
{
//boolean array with default size 5
arr[a] = true;
}
}
In main:
public static void main(String[] args) {
Test<Character> test = new Test<Character>();
test.add('A'); // throws exception
}
it always gives me arrayOutOfBoundException: 65
To my understaing the compiler only recognize the character as an ASCII integer value instead of invoking the method with generic type parameter, why does this happen, how do I make it work? EDIT: I made it work when I declare a Test of String type since there's no ASCII casting involved.
The value 'A'
is of type char
. In Java, char
is a numeric type, so it can be assigned to int
. Furthermore, when there are two overloaded methods - one taking int
, the other taking the boxed type Character
- you will get the int
one:
class Test {
static void method(int a) {
System.out.println("int");
}
static void method(Character a) {
System.out.println("Character");
}
}
> Test.method('A');
int
In particular, the integer value of 'A'
is 65, since that's its Unicode value. So you are actually calling the add(int)
method with the value 65, not the add(Character)
method, hence the IOOBE.
To fix it, either cast to Character
explicitly when calling the method, or change the names to addByIndex
and addByValue
so that Java won't select the wrong one based on the argument types.
To understand why Java chooses the add(int)
method instead of add(Character)
, requires wading through the Java Language Specification. Section §15.12 specifies how method calls are resolved:
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.
So the add(int)
method matches in the first phase because converting from a char
to an int
is not a boxing or unboxing conversion; and that method is chosen without proceeding to the second stage of method resolution where the boxing conversion from char
to Character
would be allowed.
When there's an ambiguity on which method to call due to overloading, Java clearly defines order of resolution:
See for example this question for more information.
That's why, in your case, Java prefer to implicitly cast your char into int, rather than boxing char into Character and call the generic overload.
The same problem exists with a List
and the remove
method. Consider:
List<Integer> l = new ARrayList<>();
l.add(10);
l.remove(10); // crash because it calls remove(int) rather than remove(E) with E=Integer
The solution is to don't rely on autoboxing . For example for the List above, you can write:
l.remove(Integer.valueOf(10));
And therefore, in your case:
test.add(Character.valueOf('a'), Character.valueOf('b'));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.