1

リポジトリ (Web サービスやデータベースなど) の型ハンドラーを作成する場合、値がリポジトリから読み込まれた後に型をインスタンス化する必要があります。

Stringリポジトリから値を取得し、String使用できる引数が 1 つあるコンストラクターがあるとします。戻り値の型に型パラメーターがある場合、生の型をインスタンス化する以外に何ができますか? 生の型はレガシー コードとの互換性のためだけに存在しているように見えるので、使用しないことをお勧めします。

通常は ?型パラメーターとして使用できますが (実行時に型が正しいことがわかっている場合)、ワイルドカードを型パラメーターとして使用してクラスをインスタンス化できないため、この場合は使用できません。

編集:いくつかのサンプルコード:

次のような PrimaryKey クラスがあるとします。

public class PrimaryKey<R extends RepositoryObject<R>> {
    private String value;
    public PrimaryKey(String value) {
        this.value = value;
    }
}

また、RepositoryObject を拡張する一連のクラスは、次のように定義されます。

public class RepositoryObject<R extends RepositoryObject<R>> {
    private PrimaryKey<R> pk;
    public RepositoryObject(PrimaryKey<R> pk) {
        this.pk = pk;
    }
    PrimaryKey<R> getPrimaryKey() {
        return pk;
    }
}

サブクラスの例:

public class User extends RepositoryObject<User> {
    public User(PrimaryKey<User> userId) {
        super(userId);
    }
}

クラス PrimaryKey の型処理メソッドは次のようになります。

public PrimaryKey<?> getValue(String stringValue) {
    return new PrimaryKey<>(stringValue);
}

しかし、インスタンス化するときの代わりにダイヤモンド演算子を使用しているにもかかわらず、これによりコンパイラエラーが発生します (Eclipse IDE ではなく、奇妙なことに Maven ビルドで)。型パラメーターの再帰が原因で、何らかの理由で型推論がうまく機能しない可能性があります。

4

2 に答える 2

1

Java 7 では、通常、ダイヤモンド演算子を使用してこの制限を回避できます。

Container<?> c = new Container<>(arg);

それ以外の場合は、ヘルパー ファクトリ メソッドを使用できます。

<T> Container<T> makeContainer(String arg) {
    return new Container<T>(arg);
}

...

Container<?> c = makeContainer(arg);

編集:

更新後、再帰型パラメーターを使用していることがわかります<R extends RepositoryObject<R>>。このコンパイル エラーは、ワイルドカード キャプチャと再帰型パラメータに関する javac の制限によるものです。たとえば、次の関連記事を参照してください: Java CRTP and Wildcards: Code compiles in Eclipse but not `javac`

残念ながら、回避策として生の型を使用する必要がありますが、実装の詳細として非表示にすることができます。

public PrimaryKey<?> getValue(String stringValue) {
    @SuppressWarnings("rawtypes") //a raw type is necessary to placate javac
    final PrimaryKey<?> pk = new PrimaryKey(stringValue);
    return pk;
}
于 2013-04-02T14:18:37.430 に答える
0
class SomeBogusClass extends RepositoryObject<SomeBogusClass> { }

return new PrimaryKey<SomeBogusClass>(stringValue);

真剣に、あなたのコードとは何の関係もないいくつかの偽のクラスであっても、境界を満たすものは何でもそこに置くことができます。

于 2013-04-02T18:48:56.910 に答える