
[英]Is there an upper limit on the number of Publishers or Subscribers you can have in a Reactor Java Application?
[英]What's the limit to the number of members you can have in a java enum?
假设您在 java 中有一个这样的假设枚举(纯粹出于演示目的,这不是我非常希望使用的代码):
enum Example{
FIRST,
SECOND,
THIRD,
...
LAST;
}
在编译器阻止您之前,您可以在该枚举中拥有的最大成员数是多少?
其次,当您的代码引用具有 10 个成员而不是 100 或 1,000 个成员的枚举时,运行时是否存在性能差异(除了存储大类所需的明显内存开销)?
语言规范本身没有限制。 然而,类文件有许多限制枚举的数量,上限为 65,536 (2^16) 个枚举:
字段数JVMS 4.1指定ClassFile
可以有 65,536 (2^16) 个字段。 枚举作为静态字段存储在类文件中,因此枚举值和枚举成员字段的最大数量为 65,536。
常量池JVMS 还指定常量池最多可以有 65,536 个。 常量池存储所有字符串文字、类型文字、超类型、超级接口类型、方法签名、方法名称和枚举值名称。 因此必须少于 2^16 个枚举值,因为名称字符串需要共享常量池限制。
静态方法初始化 方法的最大限制为 65,535 字节(以字节码计)。 因此 Enum 的静态初始值设定项必须小于 64Kb。 虽然编译器可能会将其拆分为不同的方法(查看错误 ID:4262078 )以将初始化分配到小块中,但编译器目前不会这样做。
长话短说,没有简单的答案,答案不仅取决于枚举值的数量,还取决于枚举拥有的方法、接口和字段的数量!
找出此类问题答案的最佳方法是尝试。 从一个小的 Python 脚本开始生成 Java 文件:
n = input()
print "class A{public static void main(String[] a){}enum B{"
print ','.join("C%d" % x for x in range(n))
print '}}'
现在尝试使用 1,10,100,1000... 工作正常,然后 BAM:
A.java:2: 代码太大 C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20 ,C21,C22,...
好像我达到了某种内部限制。 不确定它是否是记录在案的限制,是否依赖于我的编译器的特定版本,或者是否与系统相关的限制。 但对我来说,限制在 3000 左右,似乎与源代码大小有关。 也许您可以编写自己的编译器来绕过此限制。
我认为枚举值的最大数量将略低于类中字段/常量池条目的最大数量 65536。 (正如我在上面的评论中提到的,实际值不应该占用常量池条目:它们可以“内联”到字节码中,但名称会。)
至于第二个问题,没有直接的性能差异,但可以想象会有小的间接性能差异,部分原因是你说的类文件大小。 另一件要记住的事情是,当您使用enum collections 时,当所有 enum 值都适合某个范围(我记得是一个字节)时,某些类会有优化版本。 所以是的,可能会有细微的差别。 不过,我不会变得偏执。
这是对原始问题的评论的扩展。
拥有大量枚举存在多个问题。
主要原因是当您拥有大量数据时,它往往会发生变化,否则您经常想添加新项目。 有一些例外,例如永远不会改变的单位转换,但在大多数情况下,您希望将这样的数据从文件读取到类集合而不是枚举中。
添加新项目是有问题的,因为它是一个枚举,你需要物理修改你的代码,除非你总是使用枚举作为集合,如果你总是将它们用作集合,为什么要让它们成为枚举?
您的数据不会改变的情况——比如您正在转换英尺、英寸等的“转换单位”。您可以将其作为枚举来执行,并且会有很多,但是通过将它们编码为枚举,您将丢失让数据驱动程序的能力。 例如,用户可以从由您的“单位”填充的下拉列表中进行选择,但同样,这不是“ENUM”用法,而是将其用作集合。
另一个问题将是围绕对您的枚举的引用的重复。 你几乎肯定会有一些非常重复的东西,比如:
if(userSelectedCard() == cards.HEARTS)
graphic=loadFile("Heart.jpg");
if(userSelectedCard() == cards.SPADES)
graphic=loadFile("Spade.jpg");
这是错误的(如果您可以眯着眼睛看无法阅读字母的地方并在代码中看到这种模式,那么您就知道自己做错了)。
如果卡片存储在卡片集合中,那么使用会更容易:
graphic=cards.getGraphicFor(userSelectedCard());
我并不是说这也不能用枚举来完成,但我是说如果没有像我上面发布的代码块那样讨厌的代码块,我看不出你将如何使用这些作为枚举。
我也不是说没有枚举的情况——有很多,但是当你得到不止几个(7 是一个很好的数字)时,你可能会更好地使用其他结构。
我想例外是当您建模具有多种类型并且每种类型都必须使用不同代码寻址的现实世界时,但即使如此,您最好还是使用数据文件将名称绑定到某些代码以运行和存储它们以散列形式存在,因此您可以使用如下代码调用它们:hash.get(nameString).executeCode()。 这样,再次,您的“nameString”是数据而不是硬编码,允许在其他地方重构。
如果您养成像这样粗暴地分解代码的习惯,您可以将许多程序的大小减少 50% 或更多。
如果你不得不问,你可能做错了什么。 实际限制可能相当高,但我认为,超过 10 个左右值的枚举将是非常值得怀疑的。 将其分解为相关的集合、类型层次结构或其他内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.