4

对于我事先对泛型的有限知识,我深表歉意

我有以下情况:

第一类:

public class PostProcess implements Serializable {
    public int          order;
    // Several other variables.

    // Constructor setting vars
    public PostProcess(){

    }

    /* Getters and setters for variables */
}

第 2 类:

public class Application extends PostProcess{
    public int      subOrder;
    // Several other variables.

    // Constructor setting vars
    public Application(){

    }

    /* Getters and setters for variables */

}

第 3 类:

public class FileOperation extends PostProcess{
    public int      subOrder;
    // Several other variables (different from class 'Application').

    // Constructor setting vars
    public FileOperation(){

    }

    /* Getters and setters for variables */

}

我试图在不同的类中实现的是对包含“FileOperation”和“Application”对象的列表进行排序,这些对象定义为:

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();

这种排序必须在这两个对象的两个字段上,即:“order”和“subOrder”。'order' 继承自 PostProcess,'subOrder' 定义在 'Application' 和 'FileOperation' 类中。

在我阅读泛型、可比、比较器和接口的整个过程中,我认为我把事情搞混了。

我正在尝试使用以下方法进行排序:

Collections.sort(processList, new PostProcessComparator());

PostProcessComparator 定义为:

public class PostProcessComparator implements Comparator<? extends PostProcess> {

    @Override
    public int compare(Object p1, Object p2) {

      int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
      if (mainOrderCompare != 0) {
        return mainOrderCompare;
      } else {
        return p1.getSubOrder().compareTo(p2.getSubOrder());
      }
    }
}

问题:

我知道我的比较器(可能还有更多)是错误的,但我不知道具体在哪里。我是来学习的;)

  1. 我注意到定义“processList”列表不是正确的方法。当我尝试将 'FileOperation' 或 'Application' 对象添加到 List 时,编译器会以“找不到适合 add(Application) 的方法”(FileOperation 相同)打我耳光。我是否错误地假设我可以使用泛型来声明我的 processList 类型?应该是正确的,因为两个类都将 PostProcess 作为它们的超类,对吗?
  2. 在我看来,用类边界定义 PostProcessComparator 应该是可行的,因为我只想能够比较将 PostProcess 作为超类的对象(因此可以访问相同的方法)。
  3. 如何访问 p1 和 p2 的 Comparator 类中的参数对象(因为我仍然需要为参数声明它们的类型:

    @Override
    public int compare(<What to put here?> p1, <And here?> p2) {
    
    }
    

我真的希望你们能帮忙!如果我不清楚某事,请告诉我并详细说明。

谢谢!

编辑

感谢 NickJ 和 Winzu,我对比较器和 ArrayList 定义进行了必要的更改。

  • 我已将 subOrder 从 Application 和 FileOperation 移至父类(并使它们受到保护)
  • 将比较器的参数化重新定义为:

    public class PostProcessComparator<T extends PostProcess> implements Comparator<T> 
    
  • 使用 Integer.compare(p1.getOrder(), p2.getOrder()) 进行初始比较器比较。

现在是最后的挑战(编译器警告) 调用时:

    Collections.sort(processList, new PostProcessComparator());

我收到警告:- [未选中] 未选中的方法调用:类集合中的方法排序应用于给定类型

    required:  List<T>,Comparator<? super T>
    found: ArrayList<PostProcess>,PostProcessComparator

在我看来,这个比较器的参数化是正确的,除了我没有检查对象类型。

这哪里出错了?

4

3 回答 3

4

我发现的唯一问题是您需要像这样参数化 PostProcessComparator:

public class PostProcessComparator<T extends PostProcess> implements Comparator<T> {

  @Override
  public int compare(T p1, T p2) {

    int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
    if (mainOrderCompare != 0) {
      return mainOrderCompare;
    } else {
      return p1.getSubOrder().compareTo(p2.getSubOrder());
    }
  }
}

现在 compare() 方法将接受正确的类(扩展 PostProcess),因此 PostProcess 的任何公共方法都可以从 complpare() 中调用

最后,您的字段不应公开。我建议使这些字段受到保护,因此子类仍然可以继承它们,但保持封装。

于 2013-10-16T09:22:31.973 回答
2

NickJ 上面的回答显示了如何实现比较器。

对于你正在做的事情,你也想改变

private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();.

ArrayList<PostProcess> processList = new ArrayList<PostProcess>();

这就是为什么您不能将 Application et FileOperation 对象添加到列表中的原因。

这有点棘手。也许这篇文章可以帮助你理解

Java 使用带有列表和接口的泛型

您还希望 SubOrder 在父类中。

import java.io.Serializable;

public class PostProcess implements Serializable {
private int          order;
private int      subOrder;
// Several other variables.

public int getSubOrder() {
    return subOrder;
}

public void setSubOrder(int subOrder) {
    this.subOrder = subOrder;
}

public int getOrder() {
    return order;
}

public void setOrder(int order) {
    this.order = order;
}

// Constructor setting vars
public PostProcess(){

}

}

最后像这样调用比较器以避免未经检查的警告:

 Collections.sort(processList, new PostProcessComparator<PostProcess>());
于 2013-10-16T09:46:18.630 回答
0

只需将其更改为:

public class PostProcessComparator implements Comparator<PostProcess> {
    @Override
    public int compare(PostProcess p1, PostProcess p2) {
      //...
    }
}

而已。您有一个比较器,可以比较任何两个实例PostProcess(并且子类的PostProcess实例是 的实例PostProcess)。

于 2013-10-17T03:30:13.103 回答