2017-09-14 4 views
1

私は次のドメインモデルを持っているとしましょう。コンパイラ警告なしでジェネリッククラスを再利用する方法

その後
public abstract class JsonSerializer<T> { 

    public abstract JsonElement toJsonElement(final T object, final Locale locale); 

    public JsonArray toJsonArray(final Collection<T> objects, final Locale locale) { 
     return objects.stream().map(t -> toJsonElement(t, locale)).collect(JsonArray::new, JsonArray::add, JsonArray::addAll); 
    } 
} 

public class FruitJsonSerializer<T extends Fruit> implements JsonSerializer<T> {} 

public abstract class Fruit {} 

public class Banana extends Fruit {} 

public class Apple extends Fruit {} 

、私はどんな果物をシリアル化したい場合、私は:

FruitJsonSerializer serializer = new FruitJsonSerializer(); 
serializer.toJsonElement(new Banana()); 
serializer.toJsonElement(new Apple()); 

をしかし、私はそれはのメンバーとして「toJsonElement」に未チェックの呼び出しであることを言って、コンパイラから警告を受けます生の種類。

実装ごとに1つのシリアライザ宣言(FruitJsonSerializer<Apple>FruitJsonSerializer<Banana>など)を使用せずにこの警告を回避するにはどうすればよいですか?

+3

「JsonSerializer 」についてはどうですか? – daniu

+0

toJsonElementは、バナナなどのコレクションと互換性のないFruitのコレクションを期待しているためコンパイルされません – ecampolo

答えて

0

?ワイルドカード

FruitJsonSerializer<? super Fruit> serializer = new FruitJsonSerializer<>(); 

編集:スーパーに拡張されました。

+1

List <0123>はCollection <?と互換性がないのでtoJsonArrayを使用するとコンパイルされません。スーパーフルーツ> – ecampolo

2

汎用パラメータは、クラスのサブセットではなく、具象クラスでなければなりません。 JsonSerializer<Apple>またはJsonSerializer<Banana>と宣言できます。パラメータがなければ、JsonSerializer<Fruit>とみなされます。

FruitJsonSerializerを汎用化したくない場合は、FruitJsonSerializer<T extends Fruit>と書いてはいけません。それはJsonSerializer<Fruit>から継承するだけで十分です。それは私の変種です:

Collection<? extends T>の汎用パラメータにはワイルドカードを使用しています。クラスAのための

+0

あなたの時間のおかげでZefick。しかし、それはコンパイルされません。私はJsonSerializerの実装についての詳細を与える質問を編集します。 – ecampolo

0

使用ジェネリック

  • クラスAを使用すると、特定のBサブクラスにいくつかのAインスタンスの使いやすさを制限したい
  • 、基底クラスやインタフェースBとの複数の異なるオブジェクトタイプを処理できるかどうか。

など。 ListはすべてのObjectサブクラスを扱うことができ、List<String>はコンパイラの型チェックによってString要素に制限され、いくつかの微妙なバグからあなたを救います。

JsonSerializerは、ジェネリックスを呼び出す有効な例です。しかし、私はFruitJsonSerializerについて疑問を持っています。

私はFruitJsonSerializerから型パラメータを削除することをお勧め:

public class FruitJsonSerializer implements JsonSerializer<Fruit> {} 

はあなたの例では、果物のあらゆる種類の非常に同じFruitJsonSerializerを使用する予定のことを意味するもので、そのFruitJsonSerializer <Apple>かは必要なさそうです他の専門分野。

たぶん私は間違っている、正しい道をそのままクラス定義を残して、あなたのインスタンスを作成:最初の1しかApplesための第二、任意のFruitのために使用することができる

FruitJsonSerializer<Fruit> generalSerializer = new FruitJsonSerializer<>(); 
FruitJsonSerializer<Apple> applesSerializer = new FruitJsonSerializer<>(); 

を。

つ以上の発言:読むためにtoJsonArray()方法を変更します。

JsonArray toJsonArray(final Collection<? extends T> objects, final Locale); 

は、そうでなければ、あなたがJsonSerializer<Fruit>List<Apple>に合格することができません。

関連する問題