这个问题很少有人遇到,但是java中定义的属性或者方法是有上限的,可以粗略的计算为65535,也就是两字节无符号数的最大值;我在这里说的上限不是运行中内存不够之类发生的上限,而是无法通过编译为class字节码文件的上限。
测试结果
首先放出测试结果
我在测试类中什么都没有干,只是不停的在创建int类型的属性,最终在65501处触发了编译错误,而注释掉一个属性编译错误就不会发生。那么65535这个数是怎么来的呢?
字节码文件结构
首先解释下java的编译过程:首先java会把后缀为java的文件通过javac命令把其中的每个类编译为一个后缀为class的文件,其中的内容是以二进制存储的字节码信息,字节码信息包括的内容如下所示:
简单来说包括:魔数、class文件版本、常量池、访问标志、类(接口)索引、字段表、方法表和属性表的集合。其中u1、u2、u4、u8是这些部分的类型,分别代表无符号一字节、二字节、四字节、八字节的类型;看到这里可能你已经猜出来了,这些都是有上限的数字,u2最大就是65535,是不是和这个有关呢?
class文件中常量池的结构存储的是字面量和各种符号引用,字面量很好解释,类型的值可以在代码中写出来的都是字面量,比如String str = “abc”; 这里abc就是一个字面量,而符号引用就是由类的名称、修饰符和字段、方法的修饰符和名称组成的内容,在运行阶段会被替换成直接引用来指向运行时常量池(这里就不多介绍了);
分析
你定义一个属性,属性的名称就被处理为一个字符串存储在常量池中;而规定 常量池 的长度的数字使用的就是u2类型。也就是说最多定义65535个属性就是上限,而实际上会有其他的内容占用常量池的几十个的位置,所以属性的数量无法达到65535的极限罢了。
不仅是属性,方法的定义也是有上限的,因为方法的名称也会存储在常量池中。
再进一步,属性的名称的长度也是有上限的,常量池中规定字符串长度的数使用的也是u2类型,方法名、类名称、属性名等等需要使用到字符串的,长度都无法超过65535.
总结
class文件最长的类型就是u8,最大能表示的就是2^64-1,理论上java不存在没有上限的部分,只不过因为太大难以触及而已。长度上限不仅仅局限这些,方法数量、代码长度等等其他你能想到的,只要你写的够多够长都可以触发上限而无法通过编译。