给定接口(它们非常大并且由语言定义生成):
interface VisitorA {
default void visit(ASTA1 node) {...}
...
default void visit(ASTA2000 node) {...}
}
interface VisitorB extends VisitorA {
default void visit(ASTB1 node) {...}
...
default void visit(ASTB1000 node) {...}
// due to language embedding all visit methods of VisitorA
// must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
}
interface VisitorC extends VisitorA {
default void visit(ASTC1 node) {...}
...
default void visit(ASTC1000 node) {...}
// due to language embedding all visit methods of VisitorA
// must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
}
interface VisitorD extends VisitorB, VisitorC {
default void visit(ASTD1 node) {...}
...
default void visit(ASTD1000 node) {...}
// due to language embedding all visit methods of VisitorA,
// VisitorB, and VisitorC must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
@Override
default void visit(ASTB1 node) {...}
...
@Override
default void visit(ASTB1000 node) {...}
@Override
default void visit(ASTC1 node) {...}
...
@Override
default void visit(ASTC1000 node) {...}
}
现在编译 VisitorA 接口(包含大约 2000 个重载方法)大约需要 10 秒。编译VisitorB 和VisitorC 接口分别需要大约1.5 分钟。 但是当我们尝试编译VisitorD接口时,Java 8编译器大约需要7分钟!
- 有人知道为什么编译VisitorD需要这么多时间吗?
- 是因为默认方法的继承吗?
- 还是因为钻石星座,VisitorB和VisitorC都扩展了VisitorA和VisitorD又扩展了VisitorB和VisitorC?
我们已经尝试过,以下解决方案有所帮助:
interface VisitorAPlain {
void visit(ASTA1 node);
...
void visit(ASTA2000 node);
}
interface VisitorA extends VisitorAPlain {
... // has same default methods as VisitorA above
}
interface VisitorBPlain extends VisitorAPlain {
void visit(ASTB1 node);
...
void visit(ASTB1000 node);
}
interface VisitorB extends VisitorBPlain {
... // has same default methods as VisitorB above
}
interface VisitorCPlain extends VisitorAPlain {
void visit(ASTC1 node);
...
void visit(ASTC1000 node);
}
interface VisitorC extends VisitorCPlain {
... // has same default methods as VisitorC above
}
interface VisitorD extends VisitorBPlain, VisitorCPlain {
default void visit(ASTD1 node) {...}
...
default void visit(ASTD1000 node) {...}
// due to language embedding all visit methods of VisitorAPlain,
// VisitorBPlain, and VisitorCPlain must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
default void visit(ASTA2000 node) {...}
@Override
default void visit(ASTB1 node) {...}
...
default void visit(ASTB1000 node) {...}
@Override
default void visit(ASTC1 node) {...}
...
default void visit(ASTC1000 node) {...}
}
而现在visitorD的编译时间只需要2分钟左右。 但这仍然很多。
- 有人知道如何将 VisitorD 的编译时间减少到几秒钟吗?
- 如果我们去掉 VisitorD, 的两个 extends 关系
extends VisitorBPlain, VisitorCPlain
,那么这个接口的编译时间大约需要 15 秒——尽管它有大约 5.000 个默认方法。但是出于强制转换的原因,我们需要 VisitorD 与 VisitorB 和 VisitorC 兼容(通过直接扩展或具有中间纯接口的间接扩展)。
我还阅读了类似问题的答案: JDK8 编译速度慢 ,但问题似乎在于泛型类型推断:“在基于泛型目标类型的重载解决方面,Java 8 中存在严重的性能退化。”
所以这有点不同,如果有人有一个小费或一个很好的解释为什么会这样;我将非常感谢。
谢谢你,迈克尔