java方法中变量用final修饰对性能有影响!你觉得呢?

2020-10-19 科技 65阅读
在java中使用final修饰类型(包括类和接口)或类的成员与修饰方法中的普通变量从JVM的角度上看是不一样的!鉴于你谈论的是用其修饰方法中普通变量的形式,故简单说一下这方面的东东。

是否使用final修饰方法中普通变量对JVM来说没有区别!使用final修饰方法中普通变量主要是为了给Java前端编译器(如javac)看的!也就是说方法中被final修饰的普通变量在前端编译时被javac检查并保证该变量不会在作用域内被改变新值,但被编译成字节码后用于修饰方法中普通变量的final就已经不存在了!说的再具体点就是你用或不用final修饰方法中普通变量而生成的字节码文件(.class文件)没有区别(建议你用某种Class文件编辑器查看一下)!!! 当然在编译过程中会扫描final关键字并对其生成词法单元(Token),同时生成的抽象语法树(AST)在未优化之前也是有区别的。
故如你所说的“普通方法中变量用final修饰的,方法结束后jvm是不会回收这个变量的,也就不会释放内存!”这个要看该变量的作用域(比如是否发生常见的方法或线程逃逸等情况)以及是否赋值为字面量(比如字符串字面量"XXX"在加载时会被拘留(intern)在运行时常量池中,而不会在方法结束后下次GC时被回收,但这与final修饰无关!) 等特殊情况,但其是否被回收与是否仅被final修饰无关!!

至于用final修饰类型(包括类和接口)或类的成员从JVM角度考虑就和上面的很不一样了,比如你谈到的被final修饰的方法,虽然从虚拟机规范层面上讲也使用invokevirtual字节码调用,但其实它已经属于非虚方法,在JVM的角度上完全可以(当然还要看具体JVM如何实现)用指向目标方法对象的指针来作为解析的结果(直接引用),而不用再通过虚方法表进行每次执行时的动态分派过程,从而提高运行效率。再比如你谈到的内联,就我所知不用final修饰的方法在运行时只要JVM判断其满足一定条件(比如常见的HotSpot虚拟机对“热点”方法的判断)时也会根据具体情况进行内联(守护内联机制或内联缓存机制)这种基础优化机制,这方面就不多说了。(有些跑题了,呵呵)

最后想说的就是不推荐仅为了有可能提高的一点执行效率而尽可能多的使用或者滥用final(同样也适用于static等关键字),首先提升程序执行效率应该更多的从算法复杂度、业务流程合理性、软件架构合理性以及后期运行时环境调优上着手,而仅从某种语法内部运行机制上打主意意义不大!当然《Effective Java》中还是给出了不少关于使用java方面有意义的指引。其次不同的JVM产品或相同JVM产品不同版本或相同版本不同JVM配置参数都可能对同一语法机制在内部有不同的运行策略,很有可能原本希望提升执行效率的手段在某种运行时环境下却成了瓶颈。再者就算不考虑代码的可读性和可维护性,但在注释时又如何去说明仅为了提升性能而用的final或其他关键字呢?(当然可以忽视掉对它们的注释,我想这也是造成楼主提问的原因。)

罗嗦了一大堆,也不知是否是你想谈论的,希望对彼此有帮助吧。
个人看法,属于原创,仅供参考,水平有限,错误难免,接受指正,谢谢。
声明:你问我答网所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系fangmu6661024@163.com