问这个问题也只是一个推测,希望有更准确的回答,目前看是没有了,自己解释下自己的理解。
应该会多占用内存,具体多大需要看项目的代码量了,我司开发了4年的game,编译出来的jar包有10M左右的大小区别,展开在内存中的话应该相近。
具体什么是LocalVariableTable呢?
贴一 @RednaxelaFX 的关于LocalVariableTable的回答java能否获取到引用的名称?www.zhihu.com
作者:RednaxelaFX
链接:https://www.zhihu.com/question/29643012/answer/45121995
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
首先,Java里的对象并没有“名字”的通用概念,
引用也没有“名字”的概念,
变量则可以有名字的概念。
以题主的例子:
Object abc = new Object();
这个变量声明,赋值符号右手边的表达式所创建出来的对象并没有名字(不是“abc”);
右手边这个表达式产生的引用也没有名字;
而这个引用通过赋值传给了左手边一个有名字“abc”的变量。
所以题主真正想问的问题就是:能否获取变量的名字。
如果变量是静态变量或者成员变量(字段),那么它们的名字作为符号信息是一直存在Class文件并带到运行时的。所以在运行时还可以把名字找出来。
但如果题主想做的事情是类似:
nameof(foo.bar); //=> "bar" nameof(this.baz); //=> "baz"
抱歉,Java没有这么方便的功能。
如果变量是参数或局部变量,则其符号信息在正常执行中是不需要的,因而也不会被保留到Class文件里。只有当从Java源码编译到Class文件时指定保留了局部变量的符号信息,才有可能在运行时知道参数或局部变量的名字。
Class文件里有一种属性表叫做LocalVariableTable,是用来记录参数与局部变量名字的符号信息表。javac编译Java源码时默认不生成这个属性表,只有指定了-g或-g:vars才会生成它。
这个属性表主要用于支持Java的调试器,以便调试器可以把某个slot里的局部变量映射到某个名字上。
一般来说,程序不应该猜测局部变量到底映射到了局部变量区的第几个slot上;但是因为局部变量区的头n个slot是用来存储方法的参数的,参数的位置与名字的映射关系倒是可以很方便的通过LocalVariableTable找出来。
因而这个表也有被调试器之外的程序“滥用”。一个经典的例子就是Spring的LocalVariableTableParameterNameDiscoverer,传给它一个java.lang.reflect.Method|Constructor,它可以返回一个数组的参数名回来。它就是通过人肉parse出Class文件里的LocalVariableTable来把信息找出来的。
顺带放个传送门:http://www.valleytalk.org/wp-content/uploads/2011/05/Java_Program_in_Action_20110727.pdf
这个场景对LocalVariableTable来说是种“滥用”,所以到Java 8的时候,Class文件格式新增了一个MethodParameters属性表专门用来存储参数名。这个属性表javac默认不生成,要指定-parameters参数来生成。Java的核心反射API添加了新的java.lang.reflect.Parameter来让代码访问这个属性表的信息。
请参考Obtaining Names of Method Parameters:https://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html
和 JEP 118: Access to Parameter Names at Runtime
言归正传,如果有一个局部变量foo,Java里有没有简单的办法可以做到:
nameof(foo); //=> "foo"
呢?
答案是没有。
要nameof()运算符,请用C# 6:C# - The New and Improved C# 6.0
想在Java语言层面添加个nameof()运算符其实不困难,稍微鼓捣下javac就好了。
真有人有需求而且愿意用定制的javac的话我可以写个patch。
但是要说服社区把nameof()运算符加到Java语言规范里就没那么容易了…