【问题标题】:Using abstract method with generic list as return type in java在java中使用带有泛型列表的抽象方法作为返回类型
【发布时间】:2022-01-22 00:42:55
【问题描述】:

我试图在一个抽象类中构建这个抽象方法并在我的一个子类中使用它,它的返回类型应该是 List / ArrayList。我真的在语法上苦苦挣扎,之前提出的大部分问题都不是我的特殊问题。

对我来说最重要的是用简单的话来描述它。

  1. 让我用一个方法
  2. 该方法的输出(返回)应该是一个......我还不知道什么对象的列表
  3. 它的原始声明是抽象的

这里是抽象类*

private int employeeID;
    private String name, sID, department;
    private double salary;

    // Constructor (empty)
    public Employee() {

    }

    // Constructor => Every Employee has at least this attributes => Subclasses may have additonal attributes
    public Employee(int employeeID, String name, String sID, double salary, String department) {
        this.employeeID = employeeID;
        this.name = name;
        this.sID = sID;
        this.salary = salary;
        this.department = department;
    }

    // Getters and Setters below
    //.......

 // Abstract method with generic list as return type
    public abstract <T> List<T> read(String path);

这是子类

public class Clerk extends Employee {

    public Clerk() {

    }

    public Clerk(int employeeID, String name, String sID, double salary, String department) {
        super(employeeID, name, sID, salary, department);
    }

    @Override
    public <T> List<T> read(String path) {
        // TODO Auto-generated method stub

        String line = null;
        List<Clerk> clerk = new ArrayList<Clerk>();

        try {
            BufferedReader reader = new BufferedReader(new FileReader(path));
            reader.readLine();

            while ((line = reader.readLine()) != null) {
                String[] clerkValues = line.split(";");
                clerk.add(new Clerk(Integer.parseInt(clerkValues[0]), clerkValues[1], clerkValues[2], Double.parseDouble(clerkValues[3]), clerkValues[4]));

            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return clerk; // Error here,Type mismatch: cannot convert from List<Clerk> to List<T>

我总是遇到错误。而且我不想将超类(Employee)构建为像 =>

这样的通用类
 public abstract class Employee <T>{
    // Code here
    }

提前感谢您的支持。

【问题讨论】:

  • 抱歉缺少abstaract 1234562的类名 => 它是公共抽象类Employee{}
  • 您可能不想将超类构建为泛型类,但您必须这样做。
  • 不能只使用抽象的泛型方法吗?我的意思是对象的变量根本不会改变。只有在子类中,我才能添加一个类来构建新对象。例如“主管”、“看门人”、“经理”等......
  • 您确定需要抽象方法吗?如果是这样,它可以返回List&lt;Employee&gt; 而不在子类中进行专门化吗?这段代码的调用者是什么样的?
  • 您的覆盖没有返回T 的列表。相反,它是Clerk 的列表。 Afaik,没有超级(抽象)类方法签名可以被覆盖以返回不同的列表类型,这似乎是您正在尝试的。考虑重写您的问题以解释您尝试使用此方法完成的任务。 (需要一个Clerk 实例来读取Clerks 的列表没有多大意义。)然后有人可以建议一个合适的模式。

标签: java list generics arraylist abstract


【解决方案1】:

您可以像这样在Employee 中声明方法:

public abstract List<? extends Employee> read(String path);

您可以将其翻译成英语,例如“读取返回某个未知类型员工的列表”。您将能够迭代列表并以其他方式从中读取,并将元素视为Employee。您将无法将新的Employee 元素添加到列表中,或者将Employee 元素作为参数传递给方法。对于这个用例,这可能没问题。

您可以在Clerk 和其他具有这样方法签名的子类中覆盖它:

public List<Clerk> read(String path)

之所以有效,是因为List&lt;Clerk&gt;List&lt;? extends Clerk&gt;子类型,而Java 允许您覆盖一个方法,其中覆盖的方法返回的类型比它覆盖的方法更具体。

如果您随后在 Clerk 类型的引用上调用 read,则返回类型将为 List&lt;Clerk&gt;,正如预期的那样。

如果Employee 类返回List&lt;Employee&gt; 而不是List&lt;? extends Employee&gt;,这将不起作用,因为List不变的,因此List&lt;Clerk&gt; 不是 List&lt;Employee&gt; 的子类型。要理解为什么会这样,请考虑 List&lt;Employee&gt; 确实 允许您向其中添加新的 Employee 元素。如果列表的实际类型是List&lt;Clerk&gt;,但编译器允许将不是Clerk 实例的其他类型的Employee 添加到列表中,则将违反列表仅包含Clerk 元素的预期,并可能导致运行时错误。

我同意 Gene 的评论,即在 EmployeeClerk 的实例上使用这些方法没有多大意义。也许有一个EmployeeReader 接口和ClerkReader 实现会更好。

【讨论】:

  • 非常感谢您@Tim Moore 的解释。在通配符“?”的帮助下,它以类似的方式对我有用。操作员。我已经尝试过您描述的方法并且效果也很好。再次感谢大家的支持。
猜你喜欢
  • 2020-10-02
  • 2014-10-16
  • 2012-12-10
  • 2015-07-18
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多