In the following code snippet, there are three versions of a method named show()
.
package overloading;
import java.util.ArrayList;
import java.util.List;
public final class Main
{
private void show(Object object)
{
System.out.println("Object");
}
private void show(List<Object> list) //Unused method
{
System.out.println("List");
}
private void show(Object[] objects)
{
System.out.println("Objects");
}
private void addToList()
{
List<String>list=new ArrayList<String>();
list.add("String1");
list.add("String2");
list.add("String3");
show(list); // Invokes the first version
String []s={"111", "222", "333"};
show(s); // Invokes the last version
}
public static void main(String[] args)
{
new Main().addToList();
}
}
In this simplest of Java code, this method call show(s);
(the last line in the addToList()
method) invokes the last version of the overloaded methods. It supplies an array of strings - String[]
and it is accepted by the receiving parameter of type Object[]
.
This function call show(list);
however attempts to invoke the first version of the overloaded methods. It passes a list of type strings - List<String>
which should be accepted by the middle version whose receiving parameter is of type List<Object>
The middle version of the methods is completely unused. It is a compile-time error, if the first version is removed.
Why does this call show(list);
not invoke this version - private void show(List<Object> list){}
- the middle one?
In short, List<Object>
is NOT List<String>
.
To "fix" your code, use the following code
private void show(List<? extends Object> list)
{
System.out.println("List");
}
Unlike arrays (which are covariant in Java), different instantiations of a generic type are not compatible to each other, not even explicitly.
With the declaration Generic<Supertype> superGeneric; Generic<Subtype> subGeneric;
Generic<Supertype> superGeneric; Generic<Subtype> subGeneric;
the compiler would report a conversion error for both castings (Generic<Subtype>)superGeneric
and (Generic<Supertype>)subGeneric
.
This incompatibility may be softened by the wildcard if ?
is used as actual type parameter: Generic<?>
is the abstract supertype for all instantiations of the generic type.
Also see
List<Object>
is not a superclass of List<String>
in java. What you are assuming is that Java has covariance on generics, which it does NOT.
What this means is that if A
is a superclass of B
, List<A>
is NOT a superclass of List<B>
A similar problem is faced in Cannot convert generic to expanded nested type , You can see if any of the work arounds there works for you.
Perhaps changing
private void show(List<Object> list)
to
private void show(List<? extends Object> list)
Would work as you would expect?
I would say it is because the parameters are different, List <Object>
Differs from List <String>
Therefore when you call the overloaded method, it would default to the first one accepting just an Object.
Here is a short example:
public class Test
{
public static void overload (Object o)
{
System.out.println ("Object");
}
public static void overload (List <Object> o)
{
System.out.println ("List Object");
}
public static void main (String [] args)
{
overload (new ArrayList <Object>()); //"List Object"
overload (new ArrayList <String>()); //"Object"
}
}
Parameterize the list with generics and everything should work.
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.