夫陶公
清风
千古,余又何人,敢称庶几
个人博客地址: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 String name="BreezAm";
name="change"; //编译错误
- final成员变量可以在
初始块中
初始化,但不可在静态块中初始化。
- 在初始化块中初始化:【
编译通过
】
public class FinalTest {private final String name;//定义一个成员变量{name = "BreezAm";//初始化块中初始化成员变量name}public static void main(String[] args) {FinalTest test = new FinalTest();String name = test.name;System.out.println(name);//BreezAmtest.name="change";//编译报错}
}
试图在静态初始化块
中初始化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成员变量可以在静态初始化块
中初始化,但不可以在初始化块
中初始化。
- 在
静态初始化块
中初始化成员变量【编译通过
】
public class FinalTest {private static final String name;// 定义一个静态、不可变的变量static {name = "BreezAm";//在静态初始化块中初始化}public static void main(String[] args) {String name = FinalTest.name;System.out.println(name);//BreezAm}
}
- 试图在
静态初始化块
中初始化成员变量【编译报错
】
public class FinalTest {private static final String name;// 编译报错{name = "BreezAm";//在初始化块中初始化}public static void main(String[] args) {String name = FinalTest.name;System.out.println(name);//BreezAm}
}
- 在类的
构造器
中初始化,但静态final成员变量
不可以在构造函数中初始化。
- 在
构造器
中初始化非静态
final成员变量【编译通过
】
public class FinalTest {private final String name;// 定义一个成员变量【未初始化】public FinalTest() {name = "BreezAm";//在构造器中初始化final类型的成员变量}public static void main(String[] args) {FinalTest test = new FinalTest();String name = test.name;System.out.println(name);//BreezAm}
}
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:30
final参数
用来表示这个
参数
在这个函数内部
不允许被修改
案例:
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成员变量 编译失败}
}