虽然我知道为了安全起见可以使用密封,但有些人在叶子节点上使用sealed关键字作为优化技术。
这有助于优化?为什么编译器不够聪明,无法自己解决这个问题?
答案 0 :(得分:4)
假设您有一个在叶类中重写的虚方法。这肯定将不会被进一步覆盖,因此JIT编译器可能会为已知属于该叶类的目标内联调用该方法。我不知道JIT 实际是否执行此优化,请注意。
请注意,在Java中,HotSpot JVM甚至可以对非最终类执行此优化,因为它是一个多遍JIT:它可以乐观地假设没有任何东西会覆盖虚方法,然后撤消其优化,如果正在加载的类 覆盖它。当然,在Java中默认使用虚拟方法,这比C#中的方法更重要。 (即使默认不应该重要,它们显然也是如此。)
就个人而言,我特别出于优化或安全原因而不使用sealed
:我使用它是因为设计继承(正确)是 hard 。我同意“继承设计或禁止设计”这一概念,并且一般认为,不能从一个阶级中获得的偶然痛苦可以通过免于担心继承而得到补偿。 YMMV。
答案 1 :(得分:3)
不,它在优化方面没有帮助。不是我从剖析中看到的东西。
答案 2 :(得分:3)
在密封类中,对虚方法的调用可以绕过通常的虚方法查找,而是直接转到最派生的虚方法实现。原则上,编译器/ JIT也可以内联这些调用。
编译器无法解决非密封类,因为任何代码都可能在编译后出现并从类继承:编译器必须假设最坏的情况。
答案 3 :(得分:3)
这是一个错误的优化;我宁愿使用它来确保如果我不期望继承,我不会获得继承。编译器仍然将所有实例调用(到类)作为虚拟调用发出,但是可能 JIT可以以不同方式对其进行优化,并且只是进行空检查和静态调用(如果没有被覆盖)。可能。
还有一些更深奥的案例,例如当特定接口的存在会导致它在运行时被区别对待时 - 而是利用那些场景(取决于sealed
)需要通过ILGenerator
等生成运行时代码。