如何在不收到编译器警告的情况下重用泛型类

时间:2017-09-14 13:21:07

标签: java generics

让我们说我有以下域模型,我简化了一点仅用于说明目的。

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());

但是我从编译器那里得到一个警告,说它是对&#34; toJsonElement&#34;的未经检查的调用。作为原始类型的成员。

如果每个实施都没有一个序列化程序声明(FruitJsonSerializer<Apple>FruitJsonSerializer<Banana>等),我该如何避免此警告?

3 个答案:

答案 0 :(得分:2)

通用参数应该是具体类,而不是类的子集。您可以声明JsonSerializer<Apple>JsonSerializer<Banana>。如果没有参数,则将其视为JsonSerializer<Fruit>

如果您不想FruitJsonSerializer通用,那么就不应该写FruitJsonSerializer<T extends Fruit> if。从JsonSerializer<Fruit>继承它就足够了。这是我的变体:

public static interface JsonSerializer<T> {
    JsonElement toJsonElement(final T object);
    JsonArray toJsonArray(final Collection<? extends T> objects, Locale locale);
}

public static class FruitJsonSerializer implements JsonSerializer<Fruit> {}

请注意,通配符用于Collection<? extends T>的通用参数。

答案 1 :(得分:0)

你可以用吗?通配符

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

编辑:已更改延伸至超级。

答案 2 :(得分:0)

如果

,则使用泛型作为A类
  • 类A可以使用基类或接口B处理多个不同的对象类型,
  • 您希望将某些A实例的可用性限制为特定的B子类。

E.g。 from concurrent.futures.thread import ThreadPoolExecutor from threading import Condition def func(e: ThreadPoolExecutor, c: Condition, val: int): print(val) if val < 5: # A case when I need to submit a new task e.submit(func, e, c, val + 1) with c: c.notify() with ThreadPoolExecutor(max_workers=5) as e: c = Condition() for i in range(10): print(e._work_queue.qsize()) e.submit(func, e, c, 1) with c: while not e._work_queue.qsize() == 0: c.wait_for(lambda: e._work_queue.qsize() == 0) 可以处理所有List个子类,并且Object通过编译器类型检查限制为List<String>元素,从而使您免于某些类型的微妙错误。

您的String是一个有效的例子,要求提供泛型。但我怀疑JsonSerializer

我建议从FruitJsonSerializer中删除type参数:

FruitJsonSerializer

您的示例意味着您计划对任何类型的Fruit使用完全相同的FruitJsonSerializer,因此似乎不需要public class FruitJsonSerializer implements JsonSerializer<Fruit> {} 或任何其他专业化。

也许我错了,然后按原样保留类定义,并以正确的方式构建实例:

FruitJsonSerializer <Apple>

第一个可用于任何FruitJsonSerializer<Fruit> generalSerializer = new FruitJsonSerializer<>(); FruitJsonSerializer<Apple> applesSerializer = new FruitJsonSerializer<>(); ,第二个仅用于Fruit

还有一句话:将Apples方法更改为:

toJsonArray()

否则您将无法将JsonArray toJsonArray(final Collection<? extends T> objects, final Locale); 传递给List<Apple>