学习java的时候经常会被修饰符搞糊涂,这里总结下static final和final的区别。java
一、static 强调只有一份,final 说明是一个常量,final定义的基本类型的值是不可改变的,可是fianl定义的引用对象的值是能够改变的,下面举个例子来讲明:程序员
package DifStaticFinalAndFinal; class SelfCounter { private static int counter; private int id=counter++; public String toString(){ return "SelfCounter: "+id; } }
package DifStaticFinalAndFinal; class WithFinalFields { static final SelfCounter wffs=new SelfCounter(); final SelfCounter wff=new SelfCounter(); public String toString(){ return "wff= "+wff+",\n wffs= "+wffs; } }
主函数:函数
package DifStaticFinalAndFinal; public class StaticFinal { public static void main(String[] args) { System.out.println("First Object:"); System.out.println(new WithFinalFields()); System.out.println("Second Object:"); System.out.println(new WithFinalFields()); } }
运行结果:性能
First Object: wff= SelfCounter: 1, wffs= SelfCounter: 0 Second Object: wff= SelfCounter: 2, wffs= SelfCounter: 0
分析为何wff两次的运行结果不一样,而wffs两次的运行结果相同?学习
由于wffs这个容器是用static final来定义的,static 强调只有一份,所以只有一个值,spa
而final修饰的引用是能够变化的,所以wff的值是能够变化的,这也是final修饰基本类型和引用的不一样。code
二、在方法中将参数指明为final时,在使用该方法时,能够读参数可是没法使用该参数。对象
package cn.qdu.chapter7_example; public class FinalArguments { void with(final Gizmo g){ } void without(Gizmo g){ g=new Gizmo(); g.spin(); } int g(final int i){return i+1;} public static void main(String[] args) { FinalArguments bf=new FinalArguments(); bf.with(null);//无论这里的参数换成什么,都是执行void(final Gizmo g)方法,没法更改参数 bf.without(null); } }
三、为何使用final方法呢?blog
缘由有两个。其一是把方法锁定,确保在继承中使用方法行为不变,而且不会被覆盖;继承
其二是效率,若是一个方法指明为final,就是赞成编译器将针对该方法的全部调用都转为内嵌调用。 转为内嵌调用的目的是节省开销,由于编译器发现一个final方法调用命令时,会跳过程序代码这种正常方式而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,而后跳回并清理栈中的参数,处理返回值),而且以方法体中的实际代码的副原本替代方法调用。可是若是一个方法很大,程序很膨胀,就会看不到内嵌带来的任何性能的提升。
四、final和private关键字
类中全部private方法都隐式地指定为是final的,由于private关键字只能被本类调用,其余类中的方法也没法覆盖private修饰的方法,所以和加上final效果是同样的。
五、当某个类的总体定义为final时,代表该类不能被继承,方法不能被覆盖,且final类中的全部方法都隐式指定为是final的,方法声明为final后还能够有效地“关闭”动态绑定。
六、static加载类的动做只发生一次。
最后,说了这么多,也要对final作一个客观的评价。若方法或类不想让别人来继承和修改,设定为final是明智的,可是在团体中这样会阻碍其余程序员经过你想不到的合理的途径来复用类,这样的话final方法就显得过于严苛了。