java方法中变量用final修饰对性能有影响!你觉得呢? 35
最近新上手一个二次开发项目,此项目中成员方法的中变量基本都用final修饰符修饰,看过之后心里很拉闷!为啥呀,为了定义常量也不要做成这样呀!据我理解,如果方法用final...
最近新上手一个二次开发项目,此项目中成员方法的中变量基本都用final修饰符修饰,看过之后心里很拉闷!为啥呀,为了定义常量也不要做成这样呀!
据我理解,如果方法用final修饰的话对性能到还有很大的提神,因为jvm会寻找机会内联,省掉了进栈出栈等等操作,但是普通方法中变量用final修饰的,方法结束后jvm是不会回收这个变量的,也就不会释放内存!这样系统的性能肯定会大大的降低!
以上为一己之见,欢迎大家点评!谢谢 展开
据我理解,如果方法用final修饰的话对性能到还有很大的提神,因为jvm会寻找机会内联,省掉了进栈出栈等等操作,但是普通方法中变量用final修饰的,方法结束后jvm是不会回收这个变量的,也就不会释放内存!这样系统的性能肯定会大大的降低!
以上为一己之见,欢迎大家点评!谢谢 展开
8个回答
展开全部
在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或其他关键字呢?(当然可以忽视掉对它们的注释,我想这也是造成楼主提问的原因。)
罗嗦了一大堆,也不知是否是你想谈论的,希望对彼此有帮助吧。
个人看法,属于原创,仅供参考,水平有限,错误难免,接受指正,谢谢。
是否使用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或其他关键字呢?(当然可以忽视掉对它们的注释,我想这也是造成楼主提问的原因。)
罗嗦了一大堆,也不知是否是你想谈论的,希望对彼此有帮助吧。
个人看法,属于原创,仅供参考,水平有限,错误难免,接受指正,谢谢。
展开全部
final类一定是静态类,所以是有影响的。
解释:final类会在程序初始化过程中进行加载,这样的会就会一直存在于内存中,增加内存负担,但是这个也得看具体需求的,如果是本参数多次被使用,定义为final的话,后续就不需要每次创建对象,这个时候实际上是对性能有利的,所以只能是具体问题具体分析。
解释:final类会在程序初始化过程中进行加载,这样的会就会一直存在于内存中,增加内存负担,但是这个也得看具体需求的,如果是本参数多次被使用,定义为final的话,后续就不需要每次创建对象,这个时候实际上是对性能有利的,所以只能是具体问题具体分析。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
你想多了,final只是让变量无法改变而已,就好比String类,String是Object下直属final类,你用的多了会有影响么?只不过定义的一句话不让随便变化而已嘛。
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
所有的变量都用final?那肯定有问题啊
final只是代表是不可变的,不能被继承的
全都用的话,性能会有影响,不过不大,毕竟变量所占内存大不了
都是比特位了,多少个才能到兆级啊,对吧
final只是代表是不可变的,不能被继承的
全都用的话,性能会有影响,不过不大,毕竟变量所占内存大不了
都是比特位了,多少个才能到兆级啊,对吧
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
很明显推荐答案不够专业
LZ的确对JVM有所了解
这个和实现JVM也有关系
理论上这个是会影响性能的
LZ分析也有道理
不过还不够透彻
有些东西还是多看看书就明白了
LZ的确对JVM有所了解
这个和实现JVM也有关系
理论上这个是会影响性能的
LZ分析也有道理
不过还不够透彻
有些东西还是多看看书就明白了
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询