在 Android 的上下文中,Sealed 类 的性能影响是什么?

What is the Performance impact of Sealed Classes in the context of Android?

在Android中,由于性能问题,建议不要使用枚举。直到最近,在 Google IO 2018 中宣布枚举现在可以安全使用,尽管对于性能更高的应用程序仍然建议避免使用枚举。

我的问题是:

我们可以在 android 中广泛使用 kotlin sealed 类 吗?

似乎 sealed 类 是枚举的扩展。如果是这样,我们应该使用类似于枚举的密封 类 吗?

提前致谢。

密封 classes 的性能影响与任何其他 classes 相同。如果您创建一个 class 扩展密封 class 的实例,它将是一个新实例,因此需要对其进行垃圾回收。如果你有一个 object 扩展一个密封的 class,它将是一个单例并且不需要被收集(就像一个枚举常量)..

在 Android 上远离 enum 的建议被夸大了。避免使用枚举对于 Android API 来说很有意义:它们大量使用特殊常量,应用程序中有很多这样的对象,而且它们对性能至关重要。

您的自定义应用程序代码可能只想使用几个枚举来表达业务逻辑中的实体。创建十几个甚至几百个 enum 个实例将留下难以察觉的足迹。

同样的建议也适用于密封 类:一定要使用它们并提高代码质量。仅当您计划着手构建具有成千上万个类似枚举的常量和 类.

的 100 KLOC 应用程序时,才停止考虑您的选择

枚举

垃圾回收

在幕后,枚举是 class 的静态成员,因此它们不会被垃圾回收。它们会在您的应用程序的整个生命周期内保留在内存中。这可能是好的,也可能是坏的。

垃圾收集过程在 CPU 使用方面非常昂贵。对象创建也是如此,你不想一次又一次地创建相同的对象。因此,使用枚举,您可以节省垃圾收集和对象创建的成本。这是好处。

缺点是即使不使用,枚举也会保留在内存中,这样可以一直占用内存。

需要考虑的因素

如果您的应用中有 100 到 200 个枚举,则无需担心所有这些。但是当你有更多的时候,你可以根据枚举的数量、它们是否会一直被使用以及分配给你的 JVM 的内存量等事实来决定是否应该使用枚举。

比较

枚举值的比较在 when 表达式中更快,因为在底层它使用 tableswitch 来比较对象。

Android

在Android中,启用优化后,Proguard会将没有函数和属性的枚举转换为整数。这样,您就可以在编译时获得枚举的类型安全性,并在运行时获得整数的性能!


密封类

垃圾回收

Sealed classes 只是常规的 classes,唯一的例外是它们需要在同一个包和同一个编译单元中扩展。因此,它们的性能相当于常规 classes.

密封 classes 子类型的对象像常规 classes 的对象一样被垃圾收集。因此,您必须承担垃圾收集和对象创建的成本。

需要考虑的因素

当您的内存限制较低时,如果您需要数千个对象,您可以考虑使用密封的 classes 而不是枚举。因为垃圾收集器可以在内存不足且对象未被使用时收集对象。

如果您使用 object 声明来扩展密封的 class,对象将作为单例并且不会被垃圾收集,这种行为类似于枚举。但是加载关联的 classes 并将它们保存在内存中会产生额外的成本,因为 object 声明关联的 classes 与引擎盖下的对象具有相同的名称。

比较

密封 class' 类型的比较在 when 表达式中较慢,因为在幕后它使用 instanceof 来比较类型。在这种情况下,枚举和密封 classes 之间的速度差异非常小。仅当您在循环中比较数千个常量时才重要。

Android

Proguard 没有像密封 classes 的枚举那样的任何整数优化。因此,如果您只想在 Android 中拥有没有函数和属性的常量,坚持使用枚举是一个更好的主意。


就是这样!希望对您有所帮助。