Overloading Java function with List<> parameter

18,920

Solution 1

If you make both classes implement a common interface,

interface CustomerNumber {
    String getCustomerNumber();
}

public class Customer implements CustomerNumber {
  ...
  public String getCustomerNumber();
  ...
}

public class Applicant implements CustomerNumber {
   ....
   private Customer c;
   public Customer getCustomer() { return c; }
   public String getCustomerNumber() { return getCustomer().getCustomerNumber(); }
   ...
}

then you might be able to do what you want with just a single method:

public void processCustomerNumbers(List<? extends CustomerNumber> appList) {
    for (Customer c: appList) {
        processCustomerNumber(c.getCustomerNumber());
    }
}

Solution 2

The thing about generics in Java is that generic types are erased at runtime, so both of these methods compile to the same signature. You will need to have separate method names, or check the type of the list elements at runtime.

Solution 3

One way to workaround this issue would be to define custom list types like this:

class CustomerList extends ArrayList<Customer> {
    ...
}

class ApplicantList extends ArrayList<Applicant> {
    ...
}

Then the following overloading would be legal:

public void processCustomerNumbers(CustomerList custList)

public void processCustomerNumbers(ApplicantList appList)

However, I don't think that this would be a good idea. For a start, it hardwires particular implementation classes into your application's APIs.

A better approach is to define a common interface for Customer and Applicant that allows you to process them with one processCustomerNumbers method. (As described at length in other answers.)

Solution 4

Generics have what is known as type erasure - List<Customer> and List<Applicant> are the same type, the compiler just places compile-time restrictions on what you can do with them.

You could check the type of the first object in the list and call a (differently-named) internal method based on that.

Solution 5

Use array instead.

public void processCustomerNumbers(Customer[] custList)
...

public void processCustomerNumbers(Applicant[] appList)
...

When you try to call these methods with a list, convert the list to array:

List<Customer> customers;
List<Applicant> applicants;
...
processCustomerNumbers(customers.toArray(new Customer[]{});
processCustomerNumbers(applicants.toArray(new Applicant[]{});
Share:
18,920
MadMurf
Author by

MadMurf

An Irishman in Brisbane, working for an Aussie IT Consulting company with worldwide clients.

Updated on June 05, 2022

Comments

  • MadMurf
    MadMurf about 2 years

    I have 2 classes

    public class Customer{
      ...
      public String getCustomerNumber();
      ...
    }
    
    public class Applicant{
       ....
       private Customer c;
       public Customer getCustomer(){ return c; }
       ...
    }
    

    When presented with a list of customers or applicants I want a function which iterates the list and does something with the CustomerNumber.

    I've tried overloading the function

    public void processCustomerNumbers(List<Customer> custList)
    ...
    
    public void processCustomerNumbers(List<Applicant> appList)
    ...
    

    but these are seen as duplicate methods... is there a nice way of doing this rather than just having 2 differently named functions?

  • MadMurf
    MadMurf over 14 years
    Yeah, that was something I started looking at, checking the class and altering behaviour. Came to SO hoping there was an more elegant solution, if nothing comes up I'll continue down this route.
  • Dolph
    Dolph over 14 years
    Java did not always have generics; when they were added, the resulting bytecode was not changed.
  • danben
    danben over 14 years
    Yes, that's the reason for using type erasure - to avoid breaking backward compatibility with pre-generics code.
  • Brett
    Brett over 14 years
    The type are erased at runtime. Method overload selection is done at compile time. Therefore, there is enough information for the compiler to decide, even with erasure. However, there are binary representation and compatibility issues if this language change was to happen.
  • Brett
    Brett over 14 years
    As other question, override selection is done at compile time so erasure does not rule it out.
  • carmelolg
    carmelolg about 6 years
    In my opinion this kind of code could be classified as "spaghetti code". I prefer stackoverflow.com/a/2241584/4149078 because force you to implement object oriented code.