我最近玩的时候遇到了这个问题。基本上,我想创建一个中心类,某种类型的消费者可以在其中自行注册。然后,某些东西会为消费者发布对象,只有那些使用已发布类型的人才能收到它。
整个程序可以概括为:
public class Main
{
public interface Fruit
{
}
public class Apple implements Fruit
{
}
public class Banana implements Fruit
{
}
public interface FruitConsumer<T extends Fruit>
{
public void consume(T fruit);
}
public class Consumers<T extends Fruit>
{
Map<Class<T>, Collection<FruitConsumer<T>>> consumers = new HashMap<>();
public void register(Class<T> clazz, FruitConsumer<T> consumer)
{
consumers.putIfAbsent(clazz, new HashSet<>());
consumers.get(clazz).add(consumer);
}
public void consume(T fruit)
{
Collection<FruitConsumer<T>> cons = consumers.get(fruit.getClass());
for (FruitConsumer<T> c : cons)
{
c.consume(fruit); // <-- Breaks if T is Apple
}
}
}
public class BananaConsumer implements FruitConsumer<Banana>
{
void register(Consumers c)
{
c.register(Banana.class, this);
c.register(Apple.class, this); // <-- Why does this work?
}
@Override
public void consume(Banana banana)
{
System.out.println("Mmm, banana");
}
}
public static void main(String... args)
{
Main main = new Main();
main.run();
}
private void run()
{
Consumers consumers = new Consumers<>();
BananaConsumer bananaConsumer = new BananaConsumer();
bananaConsumer.register(consumers);
Banana banana = new Banana();
consumers.consume(banana);
Apple apple = new Apple();
consumers.consume(apple);
}
}
现在,我想我明白为什么会崩溃了。对于两个参数,编译器无法知道 Consumers.register
方法中的 T
是否是相同的 T
。编译器只能强制两个参数都满足 T extends Fruit
的要求。我想记住能够在 C++ 中使用类似的代码结构,因此这两种语言必须有一些不同的地方。我的假设正确吗?
此外,正确的处理方法是什么?我希望水果子类型的不同消费者能够注册自己,并且只收到他们自己作为消费者的水果。另外,我希望您可以将自己注册为消费者,以确保安全(我注意到只要没有人“错误”地注册自己,此代码就可以工作)。
最后,这种现象的名称是什么?基本上,我可以通过谷歌搜索什么来了解更多相关信息。
最佳答案
您正在声明 void register(Consumers c)
在BananaConsumer
并且它的参数是原始类型。你可以这样做:
public interface FruitConsumer<T extends Fruit> {
void register(final Consumers<T> c);
void consume(T fruit);
}
当你实现FruitConsumer<Banana>
时,这个参数将是一个香蕉消费者。
(我正在解释为什么该行可以在不阅读所有代码的情况下工作,并且其他答案提供的解决方案似乎对您的问题更符合逻辑。)
关于Java - 将泛型类型映射到所述类型的使用者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51482113/