无论如何都可以在Java中做这样的事情:
public interface Processor<T extends Producer> {
<T2> T2 process(T<T2> producer);
}
其中Producer被声明为Producer<T>
?
如果Java中的类型A使用类型B参数化也是通用的,是否有可能以某种方式在A中使用参数化类型的B?我知道,这很神秘。
假设我们有一个通用的Producer界面:
public interface Producer<T> {
T produce();
}
此接口的实现也是通用的。它们在生产对象的类型上没有区别,而在于它们如何生成它们,因此可能有:DatabaseProducer,RandomProducer等。
我们还有一个处理器接口。处理器的特定实现能够与生成器的特定实现一起工作,但处理器也不关心处理对象的类型。我们可以很容易地实现这样的案例:
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,只返回它生成的内容。只要生产者属于MyProducer类型,此实现将与String,Integer或其他对象的生成者一起使用。
现在问题是如何编写通用处理器接口。此接口使用Producer类型进行参数化,该方法应返回参数化类型的相关Producer。
我们做不到这样的事情:
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未绑定到任何特定类型的生成对象。从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>
。也许我在这里看不到重要的东西。
答案 0 :(得分:1)
您可以在类级别或方法级别使用泛型。如果您需要让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
接口设为通用,然后在其中使用带有原始类型的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>()
答案 1 :(得分:0)
这是不可能的,因为您的通用类型是 Non-Reifiable
不可兑换类型
可再生类型是类型信息完全可用的类型 在运行时。这包括原语,非泛型类型,原始类型, 和未绑定的通配符的调用。
不可再生类型是已删除信息的类型 按类型擦除编译时 - 对泛型类型的调用 未定义为无界通配符。不可重复的类型没有 它在运行时可用的所有信息。不可再生的例子 类型是List和List; JVM说不清楚 运行时这些类型之间的差异。如限制所示 泛型,在某些情况下,非可再生类型 不能使用:例如,在表达式的实例中,或作为 数组中的元素。
可以通过在界面中使用其他类型来完成非常简单的解决方法:
public interface Processor<T extends Producer, T2> {
T2 process(T producer);
}
回答问题更新:
我想说在这种情况下是不可能的,因为Producer
与T
没有实际关系。可能的是在Producer
接口中创建内部类并将其用作类型:
public interface Producer<T>{
T produce();
class NotGenericType <T>{
// inner T != outter T
// do something with T ?
}
}
public interface Processor<P extends Producer>{
// NotGenericType belongs to the type P
P.NotGenericType process(P producer);
// Won't work because there is no relation between T and Producer
// P.T process(P producer);
}
但是,我没想到这会有什么用处。