考虑一个对象,该对象生成另一个对象使用的数据以生成结果.该过程封装在一个类中,中间数据不相关.
在下面的示例中,该过程在构造时进行,并且没有问题.构造函数上的type参数确保兼容的使用者/生产者.
public class ProduceAndConsume {
public interface Producer<T> {
T produce();
}
public interface Consumer<V> {
void consume(V data);
}
public <IntermediateType> ProduceAndConsume(Producer<? extends IntermediateType> producer, Consumer<IntermediateType> consumer) {
consumer.consume(producer.produce());
}
...
}
Run Code Online (Sandbox Code Playgroud)
如果我希望存储对生产者/消费者的引用并稍后进行处理,那么代码将变为:
public class ProduceAndConsume<IntermediateType> {
public interface Producer<T> {
T produce();
}
public interface Consumer<V> {
void consume(V data);
}
private Producer<? extends IntermediateType> producer;
private Consumer<IntermediateType> consumer;
public ProduceAndConsume(Producer<? extends IntermediateType> producer, Consumer<IntermediateType> consumer) {
this.producer = producer;
this.consumer = consumer;
}
...
private void doLater() {
consumer.consume(producer.produce());
}
}
Run Code Online (Sandbox Code Playgroud)
这会向类引入泛型类型参数,并强制在任何实现中指定它.
我的问题是,有什么方法可以避免这种情况吗?中间数据类型不由此类生成,存储或使用,并且与类的用户无关.假设IntermediateType可以在某处指定类型参数,编译器具有强制类型一致性所需的所有信息.
请注意,这是一个简化的示例,实际的类在构造后的某个时间异步和定期运行处理.
使用类型变量将生产者和使用者存储在内部类中:
public class ProduceAndConsume {
private class Inner<IntermediateType> {
private Producer<? extends IntermediateType> producer;
private Consumer<IntermediateType> consumer;
// Constructor omitted.
private void doLater() {
consumer.consume(producer.produce());
}
}
private final Inner<?> inner;
public <IntermediateType> ProduceAndConsume(Producer<? extends IntermediateType> producer, Consumer<IntermediateType> consumer) {
this.inner = new Inner<>(producer, consumer);
}
private void doLater() { // Or just invoke inner.doLater() directly.
inner.doLater();
}
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以强制生产者和使用者在以后需要使用它们时相关,但之后在ProduceAndConsume实例中不需要该类型信息.
Producer<String> stringProducer = ...;
Consumer<Object> objConsumer = ...;
// No externally-visible type variables.
ProduceAndConsume pac1 = new ProduceAndConsume(stringProducer, objConsumer);
Run Code Online (Sandbox Code Playgroud)
但编译器强制生成器和使用者的兼容性:
Consumer<Integer> integerConsumer = ...;
// Compiler error.
ProduceAndConsume pac2 = new ProduceAndConsume(stringProducer, integerConsumer);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |