Перегрузка функции Java с помощью параметра List <>

У меня есть 2 класса

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

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

Когда представлен список клиентов или заявителей, я хочу функцию, которая выполняет итерацию списка и делает что-то с CustomerNumber.

Я попытался перегрузить функцию

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

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

но они рассматриваются как повторяющиеся методы... есть ли хороший способ сделать это, а не просто иметь две разные функции?

Ответ 1

Если вы оба класса реализуете общий интерфейс,

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(); }
   ...
}

то вы можете сделать то, что хотите, только с помощью одного метода:

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

Ответ 2

Что касается дженериков в Java, так это то, что общие типы стираются во время выполнения, поэтому оба этих метода скомпилируются под одну и ту же подпись. Вам нужно будет иметь отдельные имена методов или проверить тип элементов списка во время выполнения.

Ответ 3

В генераторах есть так называемое стирание типа - List<Customer> и List<Applicant> - это один и тот же тип, компилятор просто устанавливает ограничения времени компиляции на то, что вы можете с ними делать.

Вы можете проверить тип первого объекта в списке и вызвать на нем внутренний (по-другому) внутренний метод.

Ответ 4

Один из способов решения этой проблемы - определить настраиваемые типы списков, например:

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

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

Тогда следующая перегрузка будет законной:

public void processCustomerNumbers(CustomerList custList)

public void processCustomerNumbers(ApplicantList appList)

Однако я не думаю, что это была бы хорошая идея. Для начала он прокладывает определенные классы реализации в API приложений.

Лучшим подходом является определение общего интерфейса для Клиента и Заявителя, который позволяет обрабатывать их одним методом processCustomerNumbers. (Как подробно описано в других ответах.)

Ответ 5

Вместо этого используйте массив.

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

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

Когда вы пытаетесь вызвать эти методы со списком, преобразуйте список в массив:

List<Customer> customers;
List<Applicant> applicants;
...
processCustomerNumbers(customers.toArray(new Customer[]{});
processCustomerNumbers(applicants.toArray(new Applicant[]{});

Ответ 6

Прежде чем приступать к именам методов, иерархия классов немного запутывает...

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

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

Почему заявитель и клиент должны быть разные объекты? Можете ли вы рассказать связь между этими объектами?