繁体   English   中英

方法的擦除与类型中的另一个方法相同

[英]Erasure of method is the same as another method in type

以下是一个类中的两个方法

class Developer 和 Student 是不同的,不共享任何父级。

以下两个方法具有相同的代码,并且在两个对象上调用的方法具有相同的名称,例如。 获取开始日期。

class hierarchyValidator {
    private LocalDate[][] getArrayOfTimespan(List<Developer> developers)
    {
       //here i have to call some method on developer from list
        LocalDate startDate = developer.getStartDate();
        ....
    }

    private LocalDate[][] getArrayOfTimespan(List<Student> students)
    {
       //here i have to call some method on student from list
        LocalDate startDate = student.getStartDate();
       .....
    }
}

它显示错误擦除方法与类型中的另一个方法相同

我了解同一站点上其他帖子的错误背后的原因。

如何重新分解它以便不会出现错误并且代码会干净?

您的问题是由于类型擦除造成的List的参数化类型信息在运行时被擦除,因此这些方法具有几乎相同的签名并且您的代码无法编译。

为了解决您的问题,这里有一个解决方案,它概括了DeveloperStudent的共同特征,因此对于两种给定的参数化类型只需要一个getArrayOfTimespan方法:

// common interface to Student and Developer classes
interface Datable {
    LocalDate getStartDate();
}
// dev class implementing "datable"
class Developer implements Datable {
    @Override
    public LocalDate getStartDate() {
        // TODO Auto-generated method stub
        return null;
    }
}
// student class implementing "datable"
class Student implements Datable {
    @Override
    public LocalDate getStartDate() {
        // TODO Auto-generated method stub
        return null;
    }
}
// parameter interpreted as list of super type to both dev and student
private LocalDate[][] getArrayOfTimespan(List<Datable> args)
{
    for (Datable d: args) {
        // TODO something
        LocalDate foo = d.getStartDate();
    }
    // TODO return something
    return null;
}

这是 Java 泛型的固有问题。 由于泛型类型在运行时被擦除,jvm 无法决定调用哪个版本的getArrayOfTimespan()方法,因为两者都将具有完全相同的签名:即getArrayOfTimespan(List<Object> arg1) 因此你的错误。 但是,如果我们超越 Java 泛型的表面及其局限性,Java 编译器实际上是在告诉您,您有更深层次的问题。

似乎您的StudentDeveloper类在某种程度上共享行为,因为它们都有一个同名的方法来做同样的事情: getStartDate() 这表明您可以声明一个定义此常见行为的接口,例如“Startable”,然后您只需为该接口定义一次getArrayOfTimespan()方法。

interface Startable {
   LocalDate getStartDate();
}

class Developer implements Startable { /* ... */ }

class Student implements Startable { /* ... */ }

class hierarchyValidator {
    private LocalDate[][] getArrayOfTimespan(List<Startable> startables)
    {
        // ...
        LocalDate startDate = startable.getStartDate();
        // ...
    }
}

继续这条轨道,您可能会注意到您在DeveloperStudent类之间进行了一些复制粘贴,因为我猜测它们不仅共享共同的行为,而且共享共同的结构(至少是private LocalDate startDate;字段)。 这始终表明您应该将公共结构和行为提取到抽象类中。 例如:

abstract class Person {
    private LocalDate startDate;

    public LocalDate getStartDate() {
        return this.startDate;
    }
    // ... etc ...
}

class Student extends Person{}

class Developer extends Person{}

class hierarchyValidator {
    private LocalDate[][] getArrayOfTimespan(List<Person> people)
    {
        // ...
        LocalDate startDate = person.getStartDate();
        // ...
    }
}

这不仅会为您节省大量的复制粘贴,而且还会使您的代码对其他人更清晰,并帮助您避免错误,当您在一个地方更改内容而忘记副本时。

简而言之:如果您意识到自己忙于复制粘贴,或者遇到泛型问题,则几乎总是意味着您需要继承。 如果您的类具有共同的行为(即具有相同的方法)--> 使用接口。 如果您的类共享公共结构(即具有相同的字段)--> 使用抽象类。

希望这会有所帮助,祝你好运!

通常,重构具有相同擦除的接口的正确方法是通过重命名一个或两个方法来移除重载:

class HierarchyValidator {
    private LocalDate[][] getArrayOfDeveloperTimespan(List<Developer> developers) {
       //here i have to call some method on developer from list
        LocalDate startDate = developer.getStartDate();
        ....
    }
    private LocalDate[][] getArrayOfStudentTimespan(List<Student> students) {
       //here i have to call some method on student from list
        LocalDate startDate = student.getStartDate();
       .....
    }
}

现在这两种方法不再相互重载,让您继续进行单独的实现。

我尝试了 Mena 提供的解决方案,但它仍然对我不起作用,对我有用的是子类扩展父类并传递 List<? 将 BaseClass> 这个列表扩展为一个继承的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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