Android 环境中密封类对性能有何影响?

Arc*_*nes 5 performance enums android kotlin sealed-class

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

我的问题是:

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

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

提前致谢。

Yog*_*ity 7

枚举

垃圾收集

在底层,枚举是类的静态成员,因此它们不会被垃圾收集。它们在应用程序的整个生命周期中都保留在内存中。这可能是一个优点,也可能是一个缺点。

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

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

需要考虑的因素

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

比较

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

安卓

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


密封课程

垃圾收集

密封类只是常规类,唯一的例外是它们需要在同一包和同一编译单元中进行扩展。所以,他们的表现与普通班相当。

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

需要考虑的因素

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

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

比较

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

安卓

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


就是这样!希望有帮助。


Mar*_*nik 6

远离enumAndroid 的建议有些夸张。避免枚举对于 Android API 来说是有意义的:它们大量使用特殊常量,应用程序中存在很多此类对象,并且它们对性能至关重要。

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

同样的建议也适用于密封类:无论如何使用它们并提高代码的质量。仅当您计划开始构建具有成千上万个类似枚举的常量和类的 100 KLOC 应用程序时,才停止考虑您的选择。