Java关于常量及其在编译代码中的表示的深入问题
我读了乔希·布洛赫的。我不明白这些短语:使用int枚举的程序很脆弱。因为int enum是常量变量[JLS,4.12.4],它们的int值被编译到使用它们的客户机中。如果更改了与int枚举关联的值,则必须重新编译其客户端。否则,客户端仍将运行,但其行为将不正确。 主要是检查文本。谁能用别的话给我解释一下吗
你可以在下面搜索框中键入要查询的问题!
我读了乔希·布洛赫的。我不明白这些短语:使用int枚举的程序很脆弱。因为int enum是常量变量[JLS,4.12.4],它们的int值被编译到使用它们的客户机中。如果更改了与int枚举关联的值,则必须重新编译其客户端。否则,客户端仍将运行,但其行为将不正确。 主要是检查文本。谁能用别的话给我解释一下吗
# 1 楼答案
这有两个方面:
int enums
不是像Javaenum
那样的“真正的枚举”,而是在int常量中定义/匹配的int值李>ordinal()
值。但是,如果通过在enum类中添加/删除/重新排序enum常量来更改enum的顺序,则它们各自的ordinal()
值也将更改。如果然后从数据中恢复枚举,则会加载旧的序数值,但会得到错误的枚举常量。因此,Java枚举中应该始终有一个单独的枚举ID,或者按枚举常量的名称保存和还原这只是Java在更新库时与其他语言可能发生的情况的类比# 2 楼答案
int
和其他原语存储为值,而不是用于正确枚举值的引用。现在,假设您正在使用一个int
常量,其值为5
somehwere,编译器决定将其内联,即,它用该值替换对该常量的访问一个示例假设客户机代码中的以下行:
如果编译器将其内联,字节码基本上类似于:
现在想象一下你将
intEnum
更改为7
的值。如果不在字节码之上重新编译代码,字节码仍将包含x = 5
等价物。只有重新编译客户机才能将其更新为x = 7
,并且了解并重新编译库的所有客户机可能不是那么容易,甚至不可取另一方面,对正确枚举的访问不会内联,即以下内容仍然相同:
现在,如果您要更改库并将
FIVE
替换为SEVEN
,并且客户端不会被重新编译,您应该会在运行时收到一个异常,告诉您无法找到枚举值FIVE
此外,如果您的枚举将有一个值和一个getter,例如
int getSomeValue()
,那么下面的内容也应该保持不变,即不内联(我需要确认这一点,因此如果有人有证据支持或反对这一点,请在commets中分享):现在对
getSomeValue()
的调用应该在运行时解决,因此如果从5
更改为7
,则无需重新编译客户端