【发布时间】:2021-07-14 04:26:07
【问题描述】:
我正在尝试使超类(抽象或接口)成为 ArrayList 中的引用类型(定义空 lambda)...并且实现该超类/接口的子类具有不同的 lambda表达式来隐藏超类的 null lambda。但最终发生的是,调用子类 lambda 只会调用超类的 null lambda!
示例代码:
public abstract class AbstractAction {
Consumer<AbstractAction> behavior = state -> {
System.out.println("AbstractAction: do nothing");
};
}
public class IfTrue extends AbstractAction {
Boolean var = true;
Consumer<IfTrue> behavior = state -> {
if (state.var == true) state.var = false;
System.out.println("IfTrue: " + var);
};
}
public class Compare extends AbstractAction {
Boolean var1 = true;
Boolean var2 = true;
Consumer<Compare> behavior = state -> {
if (state.var1 == state.var2) state.var1 = false;
System.out.println("IfTrue: " + var1 + " " + var2);
};
}
public class ActionList {
List<AbstractAction> list = new ArrayList<>();
public void addAction(AbstractAction abstractAction) {
list.add(abstractAction);
}
public void runActions() {
for (AbstractAction a : list) {
a.behavior.accept(a);
}
}
}
public class Main {
public static void main(String[] args) {
ActionList list = new ActionList();
list.addAction(new IfTrue());
list.addAction(new Compare());
list.runActions();
}
}
结果(显示正在运行的 AbstractAction lambda,而不是子类):
AbstractAction: do nothing
AbstractAction: do nothing
但我希望看到:
IfTrue: true
Compare: false true
我也尝试过创建一个接口,但是我不能在每个子类中拥有不同数量的成员变量,否则我会收到 Actionable 接口没有这些成员的编译时错误。但即使我确实为 Actionable 接口提供了这些变量,我也会得到相同的结果。运行 Actionable.behavior lambda 而不是子类实现。
public interface Actionable {
Boolean var = true;
Boolean var1 = true;
Boolean var2 = true;
Consumer<Actionable> behavior = state -> {
System.out.println("AbstractAction: do nothing");
};
}
有没有办法隐藏 AbstractAction 或 Actionable.behavior lambda?还是我在想这个问题都错了?我真的希望能够用不同的行为/lambda 替换 Action 对象,以将操作与执行过程本身分离。
【问题讨论】:
-
我不明白你为什么要使用 lambdas 和
Consumer。behaviour不能只是一个方法吗?如果你正在做a.behavior.accept(a);,为什么它甚至需要一个参数?你有没有打算给它自己以外的任何东西?如果是这样,你怎么能确定你给它的是正确的类型? -
@Sweeper 是的,我应该提到原因……我尝试了使用实例方法的方法,但在我的应用程序中,每个方法调用都会增加我的执行时间毫秒数,而这需要执行的业务案例时间尽可能快。我将子类本身作为参数传递的原因是,我可以在每个子类上拥有尽可能多的成员,而不必担心调用每个子类所需的不同数量的参数。 ActionList.runActions() for 循环。
-
嗯...... lambdas 将如何帮助解决这个问题?如果有的话,我认为 lambdas 有一点 more 开销。您确定 this 是您的程序所做的所有事情中的瓶颈吗?
-
也许不是。我假设 Lambdas invokeDynamic 或行为的静态方法会减少 GC 活动和每次 ActionList.runActions() 必须运行时实例化实例方法所花费的时间(可能需要每 0.01 毫秒运行一次)。你能想到另一种方法吗?我知道这有点像命令模式,但我试图尽量减少方法调用。
-
Lambda 基本上是匿名合成类的方法。把一个东西变成一个 lambda 并不能消除方法调用;它只是将其隐藏在其他地方。如果您的用例是处理器密集型的,以至于 方法调用 的存在成为瓶颈,那么您不应该使用 Java;你应该使用 C。流行的视频游戏是用 Java 编写的,你最好相信像 Minecraft 这样的东西每一帧都有 ton 的方法调用。
标签: java inheritance lambda