1

同時に、非常に単純でありながら混乱を招く質問があります。

Transformer で、変換されるクラスの型が同じ型であることを指定する方法はありますか?

明確にするために、コードを共有します。

Transformer<Set<?>, List<?>> transformer = new SetToListTransformer();

Set と List が同じ型であることを指定する方法はありますか?

また、トランスフォーマーを作成するときにこれを行いましたが、それは何の役にも立たないと思います。

private static class SetToListTransformer implements Transformer<Set<?>, List<?>> {

  @Override
  public List<?> transform(final Set<?> input) {
     return this.doTransform(input);
  }

  public <T> List<T> doTransform(final Set<T> input) {
      ...
  }
}

問題は、私は SetToListTransformer を入力することができないということです。なぜなら、私は内部にどのような型があるかをあまり気にしていないからです。それらが同じ型であることだけに気を配っています。

どんな助けでも大歓迎です!

PS:私は本当にセットをリストに変換しているのではなく、他のタイプを使用しています。コードを明確にするためにそれらを使用しただけです:)

4

4 に答える 4

1

次のように、両方のワイルドカードを同じ型パラメーターにバインドしてみてください。

class SetToListTransformer<E> implements Transformer<Set<E>, List<E>> { 
    @Override
    public List<E> transform(Set<E> from) {
        ...
    }
}
于 2013-02-18T21:28:27.567 に答える
1

クラスをジェネリックにします。

private static class SetToListTransformer <T> implements Transformer<Set<T>, List<T>> {

  @Override
  public List<T> transform(Set<T> input) {
     return this.doTransform(input);
  }

  public List<T> doTransform(Set<T> input) {
      ...
  }
}

ただし、この実装は型に関して非常に厳密であることに注意してください。整数は数値ですが、SetToListTransformer<Number> を使用して Set<Integer> から List<Number> に変換することはできません。

于 2013-02-18T21:30:43.543 に答える
0

transform一般的なワイルドカード間に関係を課す方法がないため、実装に必要な制約を強制する方法はありません。宣言?内の 2 つのそれぞれは、それぞれが未知の型を意味する運命にあり、それらを互いにバインドする方法はありません。SetToListTransformer

他の人が指摘したように、最も簡単な解決策はSetToListTransformerジェネリックにすることです。例えば:

class SetToListTransformer<T> implements Transformer<Set<? extends T>, List<T>> {

    @Override
    public List<T> transform(final Set<? extends T> input) {
        final List<T> output = new ArrayList<T>(input.size());
        output.addAll(input);
        return output;
    }
}

もちろん、これには特定の型引数でトランスフォーマーをインスタンス化する必要があります。SetToListTransformer安ければこれでいいのです。ただし、1 つのインスタンスのみを使用することを示しました。その方法は次のとおりです。

class MyTransformers {

    // There is no reason to expose SetToListTransformer now.
    // Keep it here as an anonymous class.
    private static final Transformer<Set<?>, List<?>> FROM_SET_TO_LIST =
            new Transformer<Set<?>, List<?>>() {
                @Override
                public List<?> transform(final Set<?> input) {
                    return doTransform(input);
                }
                private <T> List<T> doTransform(final Set<T> input) {
                    final List<T> output = new ArrayList<T>(input.size());
                    output.addAll(input);
                    return output;
                }
            };

    private MyTransformers() { }

    public static <T> Transformer<Set<? extends T>, List<T>> fromSetToList() {
        @SuppressWarnings("unchecked")//this is okay for any T because the impl is stateless 
        final Transformer<Set<? extends T>, List<T>> withNarrowedTypes =
                (Transformer<Set<? extends T>, List<T>>)(Transformer<?, ?>)FROM_SET_TO_LIST;
        return withNarrowedTypes;
    }
}

使用例を次に示します。

Set<Integer> intSet = new HashSet<Integer>();
intSet.add(42);
intSet.add(1337);
List<Number> numList = MyTransformers.<Number>fromSetToList().transform(intSet);
于 2013-02-18T21:45:39.303 に答える
0

Transformerその制約をインターフェースで表現することはできません。追加の制約を課すサブタイプを作成し、使用されたサブタイプTransformerを使用できます。

interface StricterTransformer extends Transformer<Set<?>, List<?>>

    public <T> List<T> transform2(Set<T> input) ;

    /** javadoc additional contract: must behave as transform2(input) */
    public List<?> transform(Set<?> input);
    // in java8 we can give a "default" impl for this interface method
    // that simply calls transform2(), so subclasses don't have to impl 
    // the transform() method, which is just boiler plate code.
于 2013-02-18T21:48:02.897 に答える