3

私は自分の問題を解決する何かを見つけるために周りを見回してきましたが、今まで運がありませんでした. 私は次のクラスを持っています:

  public interface ISort<T> {
      public List<T> sort(List<T> initialList);
  }


  public abstract class Sort<T> implements ISort<T> {
    private Comparator<? super T> comparator;

    public Sort(Comparator<? super T> comparator) {
        this.comparator = comparator;
    }

    @Override
    public List<T> sort(List<T> initialList) {
        ArrayList<T> list = new ArrayList<T>(initialList);
        Collections.sort(list, comparator);

        return list;
    }
  }


public abstract class InternalTreeItem<T> {   
    public abstract String getValue();
}

public class D extends InternalTreeItem<Integer> {
   private Integer i;

   public D(Integer i) {
       this.i = i;
   }

   @Override
   public String getValue() {
       return i.toString();
   }

   public Integer getInteger() {
       return i;
   }
}

public class DComparator implements Comparator<D> {
    @Override
    public int compare(D o1, D o2) {
        return o1.getInteger() - o2.getInteger();
    }
}

public class DSort extends Sort<D> {
    public DSort(Comparator<D> comparator) {
        super(comparator);
    }

    public DSort() {
        super(new DComparator());
    }
}

そしてテストクラス:

public class TestClass {
    @Test
    public void test1() {
        List<InternalTreeItem<?>> list= new ArrayList<InternalTreeItem<?>>();

        list.add(new D(1));
        list.add(new D(10));
        list.add(new D(5));

        ISort<?> sorter = new DSort();

        sorter.sort(list);       
    }
}

コンパイラは次の行でエラーを出します

sorter.sort(list);

と状態

The method sort(List<capture#2-of ?>)
in the type ISort<capture#2-of ?>
is not applicable for the arguments
 (List<InternalTreeItem<?>>)

OK、友人の助けを借りて数時間後、問題はsort(List<T> list, Comparator<? super T> c)抽象クラス Sort の Collections# にあることに気付きましたComparator<? extends T>

2 つのモデルがあるため、ジェネリックを使用します。1 つのモデルのスーパー クラスは 35 のクラスによってサブクラス化されたジェネリック抽象であり、2 番目のモデルには実際には 2 つの異なるスーパー クラスがあり、それらを組み合わせて再び 35 のクラスによってサブクラス化します。これらの階層は与えられたものであり、それらを変更するために私にできることは何もありません。

ここでのモデルは非常に単純ですが、要点はわかります。また、T のタイプに応じて、あるソーターまたは別のソーターを返すファクトリもあります。

誰でも助けて、私の問題の解決策を提供してもらえますか (つまり、ジェネリック リストをソートすることです。パラメーターの型は、ジェネリック スーパークラスまたはそのサブクラスの 1 つにすることができます)。

よろしくお願いします、 ドミ

4

3 に答える 3

2

これにアプローチする 1 つの方法は、変更できないクラスにラッパー クラスを使用することです。

したがって、あなたの例では、整数値に基づいてオブジェクト D のリストを並べ替えたいと考えています。オブジェクトをラッパーに入れてリストに追加すると、リストをソートする値を公開できます。

たとえば、次のようなインターフェイスを定義できます。

private interface SortableListItem<T> extends Comparable<SortableListItem<T>> {
    public T getValue();
}

次に、D のラッパー クラスを作成します。

public class DWrapper implements SortableListItem<Integer> {
    private D item;

    public DWrapper(D item) {
        this.item = item;
    }

    public Integer getValue() {
        return item.getInteger();
    }

    public int compareTo(SortableListItem<Integer> o) {
        return getValue().compareTo(o.getValue());
    }
}

ここから、リストを作成して並べ替えるのは非常に簡単です。

    D item1= new D(1);
    D item2= new D(10);
    D item3= new D(5);

    DWrapper wrapper1 = new DWrapper(item1);
    DWrapper wrapper2= new DWrapper(item2);
    DWrapper wrapper3= new DWrapper(item3);

    List<SortableListItem<Integer>> sortableList = new  ArrayList<SortableListItem<Integer>>();
    sortableList.add(wrapper1 );
    sortableList.add(wrapper2);
    sortableList.add(wrapper3);
    Collections.sort(sortableList);

もちろん、ラッパー クラスがより一般的なオブジェクトを受け入れるようにすることもできます。重要なのは、各オブジェクトが List をソートできる値 (この場合は整数) を返すことです。

于 2010-01-21T16:59:34.250 に答える
1

変数sorterの型はISort<?>です。たとえば、 がISort<String>割り当てられている可能性があります。メソッドはwhere could beのsort引数を取ります。明らかにfor を使用できないため、幸いなことに、コンパイラはエラーを指摘します。List<T>TStringList<InternalTreeItem<?>>List<String>

(注: 一般に、コーディング規約に従うことをお勧めします。Iハンガリー語の接頭辞や 1 文字のクラス名は使用しないでください。)

于 2010-01-21T15:30:30.687 に答える
0

コードを実行すると、クラスTestClassの下の行で指定したワイルドカードをキャプチャできないため、コンパイル エラーが発生することが推測できます。

ISort<?> sorter = new DSort();

私が理解しているように、ワイルドカードの出現は未知の型を表すと見なされ、コードからは型を推測することはできません(コンパイラの場合)。

しかし、コードを見ると、クラス DSort は型パラメーターを取得する方法で記述されておらず
、DSort のインスタンスの作成中に型パラメーターを渡そうとすると、エラーが発生しました。
The type DSort is not generic; it cannot be parameterized with arguments

しかし、モジュールのコードを変更することはできないと述べています(つまり、クラス DSort などを想定しています)。
したがって、エラーを修正する 1 つの方法は、ISort のインスタンスの作成中にジェネリックを使用しないことです。
以下のコードは機能し、ソートされた出力 (1,5,10) を出力します。

List<InternalTreeItem<?>> list= new ArrayList<InternalTreeItem<?>>();
list.add(new D(1));
list.add(new D(10));
list.add(new D(5));

// no generic arguments
ISort sorter = new DSort();

List<InternalTreeItem<?>> sortedList = sorter.sort(list);

for(InternalTreeItem i:sortedList) {
    System.out.println(i.getValue());
}

しかし、フォームISort is a raw type の警告が表示されます。ジェネリック型 ISort への参照は、パラメーター化する必要があります。ただし、ジェネリックを使用するコードを使用し、この形式の警告を表示することはお勧めできません。この警告は、ジェネリックを使用するために行う暗黙のキャストについて、コンパイラが確実な保証を提供できないことを意味します。

可能であれば、より良い解決策は、モジュール クラスを再設計する方法を確認することだと思います。

于 2010-01-21T15:38:29.267 に答える