【问题标题】:ArrayList with different types of objects具有不同类型对象的 ArrayList
【发布时间】:2015-06-22 22:31:33
【问题描述】:
public static void main (String[] args)
{
  SalariedEmployee se = new SalariedEmployee();
  HourlyEmployee he = new HourlyEmployee();
  se.setName("Simos");
  se.setAfm("111440000");
  se.setSalary(4500);
  he.setName("Chatzis");
  he.setAfm("011155555");
  he.setHoursWorked(200);
  he.setHourlyPayment(25);
  ArrayList list = new ArrayList();
  list.add(se);
  list.add(he);
}

所以我有两个不同类型的对象,我想将它们添加到列表中。我怎样才能使它在编译器方面是安全的。由于对象是从不同的类创建的,所以在制作列表时我不能使用泛型。或者我可以在创建列表后更改列表的类型。我的意思是我可以拥有这个

ArrayList<SalariedEmployee> list = new ArrayList<SalariedEmployee>();

添加SalriedEmployee的“se”对象,然后将泛型更改为HourlyEmployee,然后添加HourlyEmployee的“he”对象?

【问题讨论】:

标签: java generics arraylist


【解决方案1】:

看起来你可以创建通用接口Employee 并让两个类都实现它。这样你就可以使用泛型了:

List&lt;Employee&gt; list = new ArrayList&lt;Employee&gt;();

【讨论】:

  • 用户没有Employee类
  • @TheGuest 所以,他必须创建它:)
  • 如果您发现自己需要一个包含两种类型对象的集合,那么您很可能希望稍后对它们进行处理。对于他们所有人。添加这个 Employee 接口并通过一些好的设计,您将能够多态地处理 XXXEmployee 和 YYYEMployee
  • 这是抽象类而不是接口的情况。
  • @Rarw 但经验法则是的,但可能不是。无论如何它都会起作用,由 ohyez96 决定哪个更适合他的模型。
【解决方案2】:

创建界面:

Employee.java

public interface Employee {
    public void setName(String name);
    public String getName();

    public void setAfm(String afm);
    public String getAfm();

}

然后创建实现它的两个类,添加它们的独特方法:

HourlyEmployee.java

public class HourlyEmployee implements Employee {

    private String name;
    private String afm;
    private int hoursWorked;
    private int hourlyPayment;

    @Override
    public void setName(String name) {
        this.name = name;

    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setAfm(String afm) {
        this.afm = afm;
    }

    @Override
    public String getAfm() {
        return this.afm;
    }

    public int getHoursWorked() {
        return this.hoursWorked;
    }

    public void setHoursWorked(int hoursWorked) {
        this.hoursWorked = hoursWorked;
    }

    public int getHourlyPayment() {
        return this.hourlyPayment;
    }

    public void setHourlyPayment(int hourlyPayment) {
        this.hourlyPayment = hourlyPayment;
    }
}

SaliedEmployee.java

public class SalariedEmployee implements Employee {

    private String name;
    private String afm;
    private int salary;

    @Override
    public void setName(String name) {
        this.name = name;

    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setAfm(String afm) {
        this.afm = afm;

    }

    @Override
    public String getAfm() {
        return this.afm;
    }

    public int getSalary() {
        return this.salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

}

然后进行测试:

import java.util.ArrayList;

public class TestMain {

    public static void main(String[] args){
         SalariedEmployee se = new SalariedEmployee();
          HourlyEmployee he = new HourlyEmployee();
          se.setName("Simos");
          se.setAfm("111440000");
          se.setSalary(4500);
          he.setName("Chatzis");
          he.setAfm("011155555");
          he.setHoursWorked(200);
          he.setHourlyPayment(25);
          ArrayList<Employee> list = new ArrayList<Employee>();
          list.add(se);
          list.add(he);

    }
}

【讨论】:

    【解决方案3】:

    创建一个 Employee 类,这两个可以继承并在 ArrayList 中使用它

    public abstract class Employee 
    {
        public string setName(string name) { ... }
        public string setAfm(string afm) { ... }
        public int setSalary(float afm) { ... }
    }
    
    public class HourlyEmployee extends Employee
    {
    }
    
    public class SalariedEmployee extends Employee
    {
    }
    
    ArrayList<Employee> employees;
    

    这也意味着您不必为每个员工类重写 setter 方法

    【讨论】:

    • 为什么所有的类都是抽象的?
    • 1) 使用interface 比使用abstract class 更好; 2)最好使用接口声明变量的类型,即不是ArrayList&lt;...&gt; employess而是List&lt;...&gt;
    • @Andremoniy 你能解释一下为什么吗?我认为抽象类会更合适,但我愿意学习其他方式
    • 对接口进行编码确实是一种很好的做法。话虽如此,接口在场景中很有用,同时为不相关的实体带来了一些附加值,例如可克隆。在上述场景中,实体是相关的并且是家庭的一部分(员工、受薪员工等) - 抽象类是可行的方法。
    【解决方案4】:

    你为什么不创建一个超类“员工”并让两个对象都成为员工的孩子:

    class Employee { }
    class SalariedEmployee extends Employee { }
    class HourlyEmployee extends Employee { }
    
    Employee salariedEmp = new SalariedEmployee();
    Employee hourlyEmp = new HourlyEmployee();
    

    然后创建一个Employee类型的数组列表:

    ArrayList<Employee> list = new <Employee>ArrayList();
    

    【讨论】:

    • 试过了,但现在我对我使用的方法有编译器警告,因为对象是 Employee 类型,它是一个超类并且不包含我使用的方法。
    • 您可以将方法添加到超类而不是子类中,并且仅在子类中需要时才覆盖它
    【解决方案5】:

    下面的初始化添加到列表中。

    > List<Object> list = new <Object>ArrayList();
    

    要稍后从列表中读取,您可以使用 instanceof 并强制转换为您在代码中拥有的已知类型。

    【讨论】:

    • 请解释投反对票的原因。请不要只是“投反对票”。
    • 投反对票,因为对于这个问题有更好的解决方案,而不是简单地使用对象然后每次检查一个实例。如果有 100 个员工子类型怎么办?你真的会实例化每个实例吗?
    • 好点,但 OP 没有 100 个子类型。更好的方法是咨询 OP 了解他们的要求。仅仅假设 OP 应该“如何”做某事并不是一个好主意,但找出需要“什么”总是一个好主意!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多