我有一类可能有很多实例(在移动设备上),所以我试图减小尺寸。我的一个领域是" DrawTarget"表示是否正在忽略绘图操作,排队到路径或绘制到显示。我希望它只需要一个字节或更少,因为只有3个可能的值,但我也希望它是友好的代码,所以我不会有全部硬编码的数字。一种想法是使用类似的枚举:
public enum DrawTarget {
Invisible,
Path,
Canvas
}
但是根据我的阅读,Java枚举不允许您指定内存布局 - 我无法请求枚举值表示字节大小值 - 我想枚举值最终是Java中的整数大小的值。
所以我想可能在枚举中创建一个隐式转换运算符...这在Java中可能吗?或者是我在枚举中实现类似内容的最佳选择:
public static DrawTarget fromValue(byte value) {
switch (value) {
case 0:
return Invisible;
case 1:
return Path;
default:
return Canvas;
}
}
然后在我想要访问值的地方调用DrawTarget.fromValue?
或者我应该创建一个单字节类,因为显然(根据我在研究中的内容),enums基本上只是Java中的特殊类?
public class DrawTarget {
public static final byte Invisible = 0;
public static final byte Path = 1;
public static final byte Canvas = 2;
}
但是,如果我使用最后一个解决方案,如何表示枚举实例的值?我仍然需要一种方法来允许" =" operator接受类的一个静态字段...比如转换构造函数或赋值运算符重载。
但是,我怀疑任何类对象作为引用类型,每个实例都需要超过一个字节。这是真的吗?答案 0 :(得分:8)
在Java中,enum是一个具有尽可能多的实例的类,并且有值。实例是在类(枚举)加载时生成的。您使用枚举变量或枚举属性的每个地方实际上都使用对现有枚举对象之一的普通引用(枚举的实例永远不会在枚举初始化后创建)。
这意味着枚举引用的成本与任何其他对象引用一样多,通常为四个字节。这真的,真的,真的很少。
你不知道一个字节需要多少内存(真的!记住低级内存管理包含大量填充!),因此基于此的任何“优化”都将失败。在给定的体系结构中,字节字段可能占用与整数字段一样多的内存(因为它可能更快)。
如果你想写好Java,请使用enum。真。 不使用枚举的唯一理由是,如果您有一整套值,例如:drawTargets[] = new DrawTarget[100000];
如果你坚持微优化,只需使用普通字节并忘记枚举; public static final byte SOMETHING = 1;
可以进行比较(并且很难进行调试)。
我已经写了很长时间的Android程序,从未见过如此微观优化。你的情况可能是百万分之一,但我认为不是。
另外,为了让我们所有人的生活更简单,请考虑在Java代码中使用Java约定:枚举实例和公共最终静态字段应为名称LIKE_THIS
,属性likeThis
(不是{{1 }}!)。
答案 1 :(得分:3)
我认为枚举值最终是Java中的整数大小的值。
不,枚举在Java中始终是类。因此,如果您有DrawTarget
类型的字段,则该字段将成为null
或DrawTarget
的三个实例之一的引用。 (不会有更多的实例;它不像每次使用时都会创建DrawTarget
的新实例。)
我会使用枚举,然后测量内存使用情况 - 枚举逻辑上你想要什么,所以采用正常的方法编写最简单的代码,然后测试< / em>表现 - 而不是猜测瓶颈可能在哪里。
你可能想要在序列化时将值表示为单个字节,然后在反序列化时将其转换回枚举,但除此之外我会在整个代码中坚持使用枚举类型如果可能的话。
答案 2 :(得分:3)
除非android有一些处理枚举引用的特殊方法,否则对DropTarget的每次引用确实会在内存中占用多个字节。枚举是类,枚举实例是对象。因此,对枚举实例的引用与任何其他对象引用具有相同的内存。
我不会太在意它,除非你已经测量过这会导致记忆问题,并且减小尺寸会产生重大影响。
你从枚举中获得的主要是类型安全。如果方法采用DropTarget
作为参数,则您(或同事)将无法传递除DropTarget
(或null)的三个实例之一之外的任何内容。如果你使用一个字节,代码就不那么清楚,任何人都可以传递任何字节值而不是三个授权字节值。
因此,确定哪个对您最重要,并选择您喜欢的解决方案。
答案 3 :(得分:1)
您的课程只会包含对枚举的引用。每个枚举只会创建一个实例。
除此之外,考虑使用多态来实现绘图行为。
如果枚举的值是固定的,则根据所需的绘图行为为每个对象实例化不同的子类。
如果值经常更改,您可以在对象中保留对所需绘图策略的引用。对于不应绘制的对象,请参阅带有空draw()方法的对象。等
答案 4 :(得分:0)
枚举是特殊数据类型,而不是class.check oracle文档以获取更多详细信息。 枚举类型是一种特殊的数据类型,它使变量成为一组预定义的常量。变量必须等于为其预定义的值之一。