深入解析final关键字的用法
夫陶公清风千古,余又何人,敢称庶几
个人博客地址:http://blog.breez.work
文章目录
- 介绍
- 解析
- final属性
- final方法
- final参数
- final类
介绍
final用于声明属性【属性不可变】、方法【方法不可覆盖】、类(除了抽象类)【类不可被继承】
解析
final属性
被final修饰的变量不可变。【引用不可变】
public class FinalTest {public static void main(String[] args) {final StringBuffer s = new StringBuffer("Hello");s.append(" World");System.out.println(s); //输出Hello World} }public class FinalTest {public static void main(String[] args) {final StringBuffer s = new StringBuffer("Hello World");s = new StringBuffer("Hello world"); //编译报错} }
从上面可以看出final指的是引用不可变,即它只能指向初始化时指向的那个对象,不关心指向对象内容的变化。所以被final修饰的变量必须被初始化。
如何初始化:
- 在初始化块中初始化:【编译通过】
试图在静态初始化块中初始化final变量【编译报错】
public class FinalTest {private final String name;// 编译报错static{name = "BreezAm"; //编译报错,就算name定义时已经被初始化此处编译期也会报错}public static void main(String[] args) {FinalTest test = new FinalTest();String name = test.name;System.out.println(name);//BreezAm} }- 在静态初始化块中初始化成员变量【编译通过】
- 试图在静态初始化块中初始化成员变量【编译报错】
- 在构造器中初始化非静态final成员变量【编译通过】
final方法
当一个方法被声明为final时,该方法不允许任何子类重写这个方法,但子类仍然可以使用这个方法。[注意:final方法可以被重载]
另外,还有一种被称为inline(内联)的机制,当调用一个被声明为final的方法时,直接将方法主体插入到调用处,而不是进行方法调用(类似于C++中的inline),这样做可以提高程序的效率。
案例:
/*** 父类*/ public class Father {/*** 编写一个final方法*/public final void doAction(){System.out.println("我是final方法、我不可以被重写,但是你可以用噢!渣女!!");} }子类试图重写final方法【编译报错】
/*** 子类*/ public class Children extends Father {public final void doAction(){ //编译报错、因为父类doAction方法是final类型的,所以不可以被重写}public static void main(String[] args) {} }使用父类中的final方法【编译通过】
/*** 子类*/ public class Children extends Father {public static void main(String[] args) {Children children = new Children();children.doAction();} }输出:
我是final方法、我不可以被重写,但是你可以用噢!渣女!!子类重载父类中的final方法
/*** 子类*/ public class Children extends Father {/*** 重写父类中被声明为final的方法* @param a* @param b*/public final void doAction(int a,int b){ // 可以被重载,哈哈,被我发现了System.out.println("a:"+a);System.out.println("b:"+b);}public static void main(String[] args) {Children children = new Children();children.doAction(20,30);} }输出:
a:20 b:30final参数
用来表示这个参数在这个函数内部不允许被修改
案例:
public class FinalTest {/*** 编写一个带参数为final的方法** @param name*//*public void doActionFinal(final String name) {name = "我想修改name,但是编译报错了,难过!!"; //编译不通过}*//*** 编写一个带非final参数的方法** @param name*/public void doAction(String name) {System.out.println("修改前:" + name);name = "name参数不是final的,我修改成功了,一个字:巴适!"; //编译通过System.out.println("修改后: " + name);}public static void main(String[] args) {FinalTest test = new FinalTest();//test.doActionFinal("BreezAm");test.doAction("BreezAm");} }输出:
修改前:BreezAm 修改后: name参数不是final的,我修改成功了,一个字:巴适!final类
当一个类被声明为final时,此类不能被继承,所有的方法都不能被重写。但这并不表示final类的成员变量也是不可变的,要想做到final类的成员变量不可改变,必须给成员变量增加final修饰。注意:一个类不能即被声明为abstract,又被声明为final【抽象类不能声明为final】。
试图继承被声明为final的类【编译失败】
/*** 父类*/ public final class Father { } /*** 子类*/ public class Children extends Father { //编译报错}试图将一个abstract类声明为final【编译失败】
/*** 父类*/ public final abstract class Father { //编译失败,抽象类不能声明为final}修改final类的成员变量
/*** 父类*/ public final class Father {private String name = "BreezAm";private final int num = 2018010110;public void doAction() {name = "清风";//修改final类的非final成员变量 编译通过num = 2019010110;//修改final类的final成员变量 编译失败} }创作挑战赛新人创作奖励来咯,坚持创作打卡瓜分现金大奖
总结
以上是生活随笔为你收集整理的深入解析final关键字的用法的全部内容,希望文章能够帮你解决所遇到的问题。