小问题
有没有可能在 Java 中做这样的事情:
public interface Processor<T extends Producer> {
<T2> T2 process(T<T2> producer);
}
生产者声明为 Producer<T>
?
长问题
如果 Java 中的类型 A 用类型 B 参数化,类型 B 也是通用的,是否可以以某种方式在 A 中使用 B 的参数化类型?我知道,这很神秘。
假设我们有一个通用的 Producer 接口(interface):
public interface Producer<T> {
T produce();
}
这个接口(interface)的实现也是通用的。它们在生成对象的类型上没有区别,而是在生成对象的方式上有所不同,因此可能有:DatabaseProducer、RandomProducer 等。
我们还有一个处理器接口(interface)。处理器的特定实现可以与生产者的特定实现协同工作,但处理器也不关心处理对象的类型。我们可以很容易地实现这种情况:
public class MyProducer<T> implements Producer<T> {
@Override
public T produce() {
(...)
}
}
public class MyProcessor implements Processor<MyProducer> {
<T> T process(MyProducer<T> producer) {
return producer.produce();
}
}
MyProcessor 的 process() 方法获取通用的 MyProducer 并只返回它生成的内容。此实现将与 String、Integer 或其他对象的生产者一起使用,只要生产者是 MyProducer 类型即可。
现在的问题是如何编写通用处理器接口(interface)。此接口(interface)使用生产者类型进行参数化,该方法应返回相关生产者的参数化类型。
我们不能这样做:
public interface Processor<T extends Producer> {
<T2> T2 process(T<T2> producer);
}
或类似的东西:
public interface Processor<T extends Producer> {
T.T process(T producer);
}
甚至可以用 Java 实现吗?有什么理由不能或不应该支持它,或者这只是一个缺失的功能?我认为编译器可以完全理解这种情况并检查类型是否正确。
更新
具有两个参数化类型的解决方案,例如:
public interface Processor<T extends Producer<T2>, T2> {
T2 process(T producer);
}
不是我要找的。请注意,MyProcessor 未绑定(bind)到任何特定类型的生成对象。从 process() 方法返回的类型是在调用站点推断的。
我还了解类型删除的工作原理以及与之相关的问题。问题是:由于类型删除,这种情况是有问题的还是不可能的?我相信不会。
如果我们有一个常规的泛型方法,例如:
<T> T process(MyProducer<T> producer) {
return producer.produce();
}
我们称之为:
MyProducer<String> prod = (...);
String result = processor.process(prod);
那么一切都会好起来的。当然,在这种情况下,String 会被删除,process() 和 produce() 方法都会在生成的字节码中返回 Object,但编译器会理解 MyProducer.produce() 实际上会返回 String,因此 process() 也会返回 String。我不明白为什么在我的情况下它不能以同样的方式工作:
public interface Processor<T extends Producer> {
<T2> T2 process(T<T2> producer);
}
编译器从传递的生产者对象推断出调用点的返回类型,并且它可以按照与上述相同的方式证明实现是正确的。我认为现在 Java 中唯一缺少的是编译器应该注意到 T 扩展了泛型类型,所以 T<T2>
可以被视为类似于 Producer<T2>
.也许我在这里没有看到重要的东西。
最佳答案
您可以在类级别或方法级别使用泛型。如果您需要让 Processor 使用特定类型的 Producer,那么您可以这样定义 Processor:
public interface Producer<T> {
T produce();
}
public interface Processor< T, P extends Producer<T> > {
public T process(P producer);
}
public class MyProducer<T> implements Producer<T> {
@Override
public T produce() {
return null;
}
}
public class MyProcessor<T> implements Processor<T, MyProducer<T> > {
public T process(MyProducer<T> producer) {
return producer.produce();
}
}
更新 1:
我不明白使 Processor
接口(interface)通用然后在其中使用原始类型的 Producer
有什么意义。如果您不想将 Processor
参数化为任何类型的 Producer
,那么您可以在方法级别声明参数化类型:
public static interface Processor {
public <T> T process(Producer<T> producer);
}
public static class MyProcessor implements Processor{
public <T> T process(Producer<T> producer) {
return producer.produce();
}
}
//in here we wont have any compilation errors
String result = new MyProcessor().process( new MyProducer<String>() );
顺便说一句,我不喜欢你如何声明 MyProducer 是通用的,而不是展示你将如何知道在 produce()
方法中返回什么类型的对象。
更新 2:
在这种情况下,我认为我们不能不进行转换。这是另一个没有限制 Producer
的版本,需要强制转换:
public static interface Processor< P extends Producer<?> > {
public <T> T process(P producer);
}
public static class MyProcessor implements Processor< MyProducer<?> > {
@SuppressWarnings("unchecked")
public <T> T process(MyProducer<?> producer) {
return (T)producer.produce();
}
}
//again this will work without any compilation errors
String result = new MyProcessor().process( new MyProducer<String>()
关于java - 访问参数化类型的参数化类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44552019/