java在泛型方法中使用它(继承)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java在泛型方法中使用它(继承)相关的知识,希望对你有一定的参考价值。
在创建在父类中使用的lambda时,我正在尝试访问子类方法和字段。代码更容易解释:
class Parent {
List<Processor<? extends Parent>> processors;
private void doSmth() {
for (Processor<? extends Parent> processor : processors) {
processor.doJob(this); //this lines gives compile error
}
}
public void registerListeners(Processor<? extends Parent> ... subscribers) {
this.subscriberList = Arrays.asList(subscribers);
}
}
Processor
是FunctionalInterface
的地方。
public interface Processor<T extends Parent> extends BiFunction<T, Message, Boolean> {
AtomicReference<Boolean> ok = new AtomicReference<>(false);
default void doJob(T client, Message message) {
if (apply(client, message))
ok.set(true);
}
default boolean isDone() {
return ok.get();
}
}
想要使用这些类的示例:
Child childInstance= new Child(); //where Child class extends Parent
childInstance.registerListeners((child, message) -> child.callSomeChildMethod());
childInstance.doSmth(message);
在没有冗余指定参数类型的情况下创建lambda会非常酷,如下所示:
childInstance.registerListeners((Processor<Child>) (child, message) -> child.callSomeChildMethod());
(因为它总是应该是我注册监听器的类型)
问题是代码没有编译错误
incompatible types: Parent cannot be converted to capture#1 of ? extends Parent
这是合乎逻辑的(我理解其中的原因)。在java中是否有某些方法我可以使用此代码?
提前致谢!
答案
你在List<Processor<? extends Parent>> processors;
课上有Parent
的想法是不可取的。如您所见,因为您没有提到列表所具有的进程类型;无论你在哪里调用processor.doJob(anyObjectHere)
,都会以某种方式抛出错误(除非你进行显式转换)
尝试做这样的事情;
- 声明一个
Client
而不是你的Parent
,其中包含List<Processor<? extends Parent>> processors
中的处理器类型;abstract class Client<T extends Client<T>> { List<Processor<T>> processors; public void doSmth(Message message) { for (Processor<T> processor : processors) { processor.doJob(getThis(), message); } } abstract T getThis(); public void registerListeners(Processor<T> subscribers) { this.processors = Arrays.asList(subscribers); } }
- 将你的
Processor
定义改为纳入Client
而不是Parent
interface Processor<T extends Client<T>> extends BiFunction<T, Message, Boolean> { AtomicReference<Boolean> ok = new AtomicReference<>(false); default void doJob(T client, Message message) { if (apply(client, message)) ok.set(true); } default boolean isDone() { return ok.get(); } }
- 现在你可以像这样创建你的
Child
;class Child extends Client<Child> { boolean callSomeChildMethod() { return true; } @Override Child getThis() { return this; } }
- 并像以前一样打电话给他们;
Child childInstance= new Child(); //where Child class extends Parent childInstance.registerListeners((child, message) -> child.callSomeChildMethod()); childInstance.doSmth(message);
这样既没有编译错误也没有警告
另一答案
你可以简单地转换processor
对象来声明你想要传递一个派生自Parent
的类的对象(可能是Child
),并将this
转换为相同的类型。它甚至可以是通用的:
private <T extends Parent> void doSmth() {
for (Processor<? extends Parent> p : processors) {
Processor<T> processor = (Processor<T>) p; // explicit cast
processor.doJob((T) this); //no compile error
}
}
以上是关于java在泛型方法中使用它(继承)的主要内容,如果未能解决你的问题,请参考以下文章
在泛型方法中返回特定类型,具体取决于运行时没有反射或动态的枚举值