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

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

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

以下两种方法都有相同的代码和方法,两个对象都有同名的ex。 getStartDate。

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

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

我理解同一网站上其他post的错误背后的原因。

如何重新考虑它,以便错误不会存在,代码将是干净的?

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

为了解决您的问题,这里有一个解决方案,它概括了DeveloperStudent的常用function,因此对于给定的参数化类型只需要一个 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 args) { for (Datable d: args) { // TODO something LocalDate foo = d.getStartDate(); } // TODO return something return null; } 

这是Javagenerics的固有问题。 因为generics类型在运行时被擦除,所以jvm无法决定调用哪个版本的getArrayOfTimespan()方法,因为两者都具有完全相同的签名:即getArrayOfTimespan(Listarg1) 。 因此你的错误。 但是,如果我们超越Javagenerics的表面并且它的局限性,那么Java编译器实际上告诉您存在更深层次的问题。

看起来你的StudentDeveloper类在某种程度上共享行为,因为它们都有一个完全相同的方法: getStartDate() 。 这表明你可以声明一个定义这种常见行为的接口,例如“Startable”,然后你只需要为接口定义一次getArrayOfTimespan()方法。

 interface Startable { LocalDate getStartDate(); } class Developer implements Startable { /* ... */ } class Student implements Startable { /* ... */ } class hierarchyValidator { private LocalDate[][] getArrayOfTimespan(List 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 people) { // ... LocalDate startDate = person.getStartDate(); // ... } } 

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

简而言之:如果你意识到你正在忙于复制粘贴,或者如果你遇到了generics问题,那么它几乎总是意味着你需要inheritance。 如果您的类共享共同行为(即具有相同的方法) – >使用接口。 如果您的类共享公共结构(即具有相同的字段) – >使用抽象类。

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

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

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

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