简体   繁体   English

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

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

Following are two methods in a class以下是一个类中的两个方法

class Developer and Student are different and not share any parent. class Developer 和 Student 是不同的,不共享任何父级。

Both following method has same code and method called on both object have same name ex.以下两个方法具有相同的代码,并且在两个对象上调用的方法具有相同的名称,例如。 getStartDate.获取开始日期。

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

It is showing error Erasure of method is the same as another method in type它显示错误擦除方法与类型中的另一个方法相同

I understand the reason behind error from other post on same site.我了解同一站点上其他帖子的错误背后的原因。

How to re-factored it so that error wont be there and code will be clean?如何重新分解它以便不会出现错误并且代码会干净?

Your problem is due to type erasure : the parametrized type information in your List s is erased at runtime, hence the methods have a virtually identical signature and your code cannot compile.您的问题是由于类型擦除造成的List的参数化类型信息在运行时被擦除,因此这些方法具有几乎相同的签名并且您的代码无法编译。

In order to solve your problem, here's a solution that generalizes the common features of Developer and Student , thus only requiring one getArrayOfTimespan method for both given parametrized types:为了解决您的问题,这里有一个解决方案,它概括了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;
}

This is an inherent problem with Java generics.这是 Java 泛型的固有问题。 Because generic types are erased at runtime, the jvm cannot decide which version of the getArrayOfTimespan() method to call, as both will have the exact same signature: ie getArrayOfTimespan(List<Object> arg1) .由于泛型类型在运行时被擦除,jvm 无法决定调用哪个版本的getArrayOfTimespan()方法,因为两者都将具有完全相同的签名:即getArrayOfTimespan(List<Object> arg1) Hence your error.因此你的错误。 However if we look beyond the surface of Java generics an it's limitations, the Java compiler is actually telling you that you have a deeper problem.但是,如果我们超越 Java 泛型的表面及其局限性,Java 编译器实际上是在告诉您,您有更深层次的问题。

It seems that both your Student and Developer classes share behaviour to some degree, as both have an identically named method that does the same thing: getStartDate() .似乎您的StudentDeveloper类在某种程度上共享行为,因为它们都有一个同名的方法来做同样的事情: getStartDate() This would suggest that you could declare an interface that defines this common behaviour, eg "Startable" and then you will only need to define the getArrayOfTimespan() method once for the interface.这表明您可以声明一个定义此常见行为的接口,例如“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();
        // ...
    }
}

Continuing on that track you will probably notice that you are doing some copy-pasting between your Developer and Student classes, as I am guessing that they not only share common behaviour , but also common structure (at least a private LocalDate startDate; field).继续这条轨道,您可能会注意到您在DeveloperStudent类之间进行了一些复制粘贴,因为我猜测它们不仅共享共同的行为,而且共享共同的结构(至少是private LocalDate startDate;字段)。 This is always an indicator that you should be extracting your common structure and behaviour into an abstract class.这始终表明您应该将公共结构和行为提取到抽象类中。 Eg:例如:

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

This will not only save you a lot of copy-pasting, but it will also make your code clearer to others, and help you to avoid bugs, when you change things in one place and forget about the copies.这不仅会为您节省大量的复制粘贴,而且还会使您的代码对其他人更清晰,并帮助您避免错误,当您在一个地方更改内容而忘记副本时。

So in short: If you realise that you are busy copy-pasting, or if you are having generics trouble, it almost always means you need inheritance.简而言之:如果您意识到自己忙于复制粘贴,或者遇到泛型问题,则几乎总是意味着您需要继承。 If your classes share common behaviour(ie have the same methods) --> use an interface.如果您的类具有共同的行为(即具有相同的方法)--> 使用接口。 If your classes share common structure(ie have the same fields) --> use an abstract class.如果您的类共享公共结构(即具有相同的字段)--> 使用抽象类。

Hope this helps, and good luck!希望这会有所帮助,祝你好运!

Generally, a proper way to refactor an interface with identical erasures is to remove the overload by renaming one or both methods:通常,重构具有相同擦除的接口的正确方法是通过重命名一个或两个方法来移除重载:

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

Now the two methods are no longer overloading each other, letting you proceed with separate implementations.现在这两种方法不再相互重载,让您继续进行单独的实现。

I tried the solution provided by Mena but it still didnt work for me what worked for me was subclasses extending the parent class and passing List<?我尝试了 Mena 提供的解决方案,但它仍然对我不起作用,对我有用的是子类扩展父类并传递 List<? extends BaseClass> this list to a single inherited method.将 BaseClass> 这个列表扩展为一个继承的方法。

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

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