A Java class cannot have two overloaded methods that will have the same signature after type erasure. Java will generate a compile-time error for the below scenario:
public class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }
}
But my question is not that. There are two scenarios 1 and 2. I want to know, why their behavior is not the same?
Scenario 1
:
import java.util.ArrayList;
import java.util.List;
public class MethodOverload {
public static void main(String[] args) {
MethodOverload methodOverload = new MethodOverload();
//Point 1 - List here
List<Integer> mangoList = new ArrayList<Integer>();
mangoList.add(1);
mangoList.add(2);
System.out.println("Size List<Integer>:"+methodOverload.count(mangoList));
//Point 2 - ArrayList here
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("Anex");
nameList.add("Alia");
nameList.add("Maxim");
System.out.println("Size List<String>:"+methodOverload.count(nameList));
}
public <T> int count(List<T> list) {
System.out.print("Ïn side generic; ");
return list.size();
}
}
Output, for Scenario 1:
Inside generic block; Size List<Integer> : 2
Inside generic block; Size List<String> : 3
Scenario 2:
import java.util.ArrayList;
import java.util.List;
public class MethodOverload {
public static void main(String[] args) {
MethodOverload methodOverload = new MethodOverload();
//Point 3 - List here
List<Integer> mangoList = new ArrayList<Integer>();
mangoList.add(1);
mangoList.add(2);
System.out.println("Size List<Integer>:"+methodOverload.count(mangoList));
//Point 4 - ArrayList here
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("Anex");
nameList.add("Alia");
nameList.add("Maxim");
System.out.println("Size List<String>:"+methodOverload.count(nameList));
}
public <T> int count(List<T> list) {
System.out.print("Inside generic block; ");
return list.size();
}
//Point 5
public int count(ArrayList<String> list) {
System.out.print("Inside non-generic block; ");
return list.size();
}
}
Output, for scenario 2:
Inside generic block; Size List<Integer> : 2
Inside non-generic block; Size List<String> : 3
Now, my question is, how does java decide which method will call in the case of scenario 2
? In scenario 1
, where java called a single count method without any issue, then why does not java show similar behavior for scenario 2
?
In Java, method parameter types are part of the method signature
So, the method will be bounded at compile time based on parameter types. (this should not be misunderstood with polymorphic behavior of the reference variable on which the method is invoked, say methodOverload
In the above code,
List
will be bound to a method that has List
as parameter typeList
as parameter type and assume there is a method with ArrayList
as parameter. How can the compiler guarantee that the List
is actually an ArrayList
at runtime to maintain type safety promises. Since it can not, it will prohibit such binding.ArrayList
will be bound to a method that has exact type ArrayList
if present. If such method does not exist, then it will be mapped to List
method(with relevant generic type if generics is considered)Essentially,
Final thoughts
Because type erasure only applies to generic types. Java does not "erase" inheritance.
In scenario 1, the count() method signature effectively becomes this at runtime:
public int count(List<Object> list) {...}
so both mangoList (declared a List) and nameList (declared an ArrayList) fit this signature.
In scenario 2, the method signatures effectively become this at runtime:
public int count(List<Object> list) {...}
public int count(ArrayList<Object> list) {...}
Java knows how to do this (inheritance-based) overloading, long before generics came about. What it can't do is overloading based on unbound generic types, because of runtime type erasure, and that's why the compiler stops you doing that.
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.