简体   繁体   中英

Overloading of methods in Java

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM