2

そのため、インターフェイスSuperTypeと一連の実装クラスなどTypeAを取得TypeBしました。パラメータ化されたメソッドを持つトップレベルのインターフェースも取得しました。

public interface UsedByProductThing<T extends SuperType> {
    public T doStuff(T one);
}

を実装するオブジェクトを生成するファクトリ(以下を参照)を取得しましたGeneralProduct

public interface GeneralProduct<T extends SuperType> {
    T doSomething(T input);
}

実装は次のProductAとおりです。

public class ProductA implements GeneralProduct<TypeA> {
    UsedByProductThing<TypeA> in;

    public ProductA(UsedByProductThing<TypeA> in) {
        this.in = in;
        in.doStuff(new TypeA());
    }

    @Override
    public TypeA doSomething(TypeA input) {
        return null;
    }
}

そして今問題の工場:

public class GeneralFactory {
    public static <T extends SuperType> GeneralProduct<T> createProduct(
            int type, UsedByProductThing<T> in) {
        switch (type) {
        case 1:
            return (GeneralProduct<T>) new ProductA((UsedByProductThing<TypeA>) in);
            // at this point, i want to return a "new ProductA(in)" preferably
            // without casting
            // or at least without the cast of the argument.
        default:
            throw new IllegalArgumentException("type unkown.");
        }
    }
}

コメントしたように、その factory-method でキャストを使用しないようにします。戻り値の型が GeneralProduct でなければならないことは理解していますが、キャストを省略する方法は考えられません (「チェックされていないキャスト」という警告も表示されます)。また、引数のキャストを省略する方法が思い浮かびません。その場所で「安全でない」キャストを取り除く必要がある場合は、コード全体を再構築できます。ここでうまくスムーズになる方法を教えてもらえますか?

また、私の質問を好きなように編集してください - タイトルの問題を正しく解決する方法がわかりません。

どうもありがとう!

4

3 に答える 3

4

キャストを避けることはできません。

  • に変換したいin型があり、コンパイラーはそれが何であるかを知る方法がありませんUsedByProductThing<T>UsedByProductThing<TypeA>TTypeA
  • ProductA はありますが、コンパイラはそれがここGeneralProduct<TypeA>にあることも認識していません。TTypeA

キャストを回避する唯一の方法は、置き換えることTですTypeA

    public static GeneralProduct<TypeA> createProduct(
            int type, UsedByProductThing<TypeA> in) {
        switch (type) {
            case 1:
                return new ProductA(in);
            default:
                throw new IllegalArgumentException("type unkown.");
        }
    }
于 2012-09-14T12:31:45.377 に答える
0

これを行うためのきれいな方法があるかどうかはわかりません。また、誰かが「in」値と互換性のない「type」値を渡す可能性があるため、あなたが行っている方法でキャストすることは本質的に安全ではないと思います。

そうは言っても、これらの種類の固有のチェックされていないキャストは、ジェネリックを扱うときに一般的です。可能であればそれらを回避する必要がありますが、コンパイラの警告を本当に取り除きたい場合は、それができない場合があり、注釈を追加して抑制する必要があります。

@Suppress("未チェック")

代わりに、ビルダーのアプローチを採用してみませんか?

public inteface Builder<T extends SuperType> {
    public GeneralProduct<T> createProduct(UsedByProductThing<T> thing);
}

public class BuilderFactory {
    public static <T extends SuperType> Builder<T> createBuilder(Class<T> clazz) {
       if (clazz.equals(ProductA.class)) {
          return new (Builder<T>) ProductABuilder();
       }
       ...
    }
}

そして、それをそのまま使用します(ビルダーimpleを作成したと仮定します:

Builder<ProductA> builder = BuilderFactory.createBuilder(ProductA.class);
UsedByProductThing<ProductA> thing = ...;
ProductA product = builder.createProduct(thing);
于 2012-09-14T12:39:50.013 に答える
0

戻らない

"GeneralProduct<T>"

、戻ったほうがいい

"GeneralProduct<?>"

であるため、結果をキャストする必要はありません。

とにかく、「ProductA」のパラメーターをキャストする必要があります。

于 2012-09-14T12:45:11.587 に答える