一、简介
final
修饰符表示"最后的
、最终的
"含义,用来修饰类
、方法
和变量
,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
二、final类
final 类不能被继承,没有类能够继承 final 类的任何特性。
格式:
public final class TestClass{
// 类体…
}
注意: 虽然final修饰的类无法被继承,但是他也是有父类(Object)的
示例
FinalClass类
public final class FinalClass /*extends Object*/{
public void method(){
System.out.println("我是final类");
}
}
SubClass类
public class SubClass /*extends FinalClass*/ {
}
从上图红色波浪线可以看到SubClass类去继承FinalClass类编译不通过。
三、final方法
父类中的 final 方法可以被子类继承,但是不能被子类覆盖重写。
格式:
public class Test{
public final void finalMethod(){
// 方法体…
}
}
**注意:**final关键字和abstract关键字不能同时出现,final修饰的方法不能被重写,abstract修饰的方法一定要被重写,两个互相矛盾。
示例
Fu类
public class Fu {
public final void finalMethod(){
System.out.println("父类的final方法");
}
}
Zi类
public class Zi extends Fu {
// 错误写法
// @Override
// public void finalMethod(){
// System.out.println("我是子类final方法");
// }
}
从上图红色波浪线可以看出,final修饰的父类方法,子类不能覆盖重写。
子类去尝试覆盖重写会编译不通过。
四、final变量
变量一旦赋值后,不能被重新赋值。final变量赋值只能赋值一次。被 final 修饰的实例变量必须显式指定初始值
1.局部变量
被final修饰的局部变量也是不可变的,只能进行最开始的唯一一次显示初始化赋值。
注意:
对于基本数据类型来说,变量中的数据值不可变。
对于引用类型来说,变量中的地址值不可变。
示例
Person类
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类
public class FinalDemo {
public static void main(String[] args) {
// 普通局部变量是可以进行多次赋值的
int num1 = 10;
System.out.println(num1); // 10
num1 = 20;
System.out.println(num1); // 20
// 局部变量一旦被fianl修饰,就不可再改变
// final变量必须进行一次显式指定初始值
// 普通变量会自动给默认值
int num3 = 30;
System.out.println(num3); // 30
// 错误写法
// final变量不会自动给默认值 必须进行一次显式指定初始值
// final int num2;
// System.out.println(num2); // Variable 'num2' might not have been initialized
// 正确写法
// 保证只有唯一一次赋值就行
final int num4 = 40;
System.out.println(num4);
//num4 = 100; // 错误写法 前面已经初始化赋值过一次了
// 对于基本数据类型来说,变量中的数据值不可变
// 对于引用类型来说,变量中的地址值不可变
// 两次new都会申请一块内存 所以内存地址不同
Person p1 = new Person("刘德华");
System.out.println(p1);
System.out.println(p1.getName()); // 刘德华
p1 = new Person("迪丽热巴");
System.out.println(p1);
System.out.println(p1.getName()); // 迪丽热巴
System.out.println("===================");
final Person p2 = new Person("古天乐");
System.out.println(p2.getName()); // 古天乐
// 错误写法 上一行已经进行过一次赋值了,不可再赋值
//p2 = new Person("张学友");
// 每new一次都会重新申请一块内存 所以地址会改变 final修饰的引用类型变量的地址不能变
// 但是地址指向的内容可以变
p2.setName("张学友");
System.out.println(p2.getName()); // 张学友
}
}
2.成员变量
被final修饰的成员变量来说也是不可变的。
注意:
1.由于成员变量具有默认值,所以使用final修饰后,必须自己赋值,不会再给默认值了。
2.final成员变量的赋值方式有2种。一种是直接赋值,一种是构造函数赋值。只能选择其中一种赋值方式。
3.如果使用构造函数进行final成员变量的赋值,要保证所有的重载构造函数都会对final成员变量赋值。
示例
Student1类
// final成员变量使用直接赋值的方式
public class Student1 {
private final String name = "范冰冰";
public Student1() {
}
public Student1(String name) {
}
public String getName() {
return name;
}
// final修饰的成员变量么使用构造函数赋值,要么使用直接赋值的方式
// 所以final成员变量的setter方法不再需要
// public void setName(String name) {
// this.name = name;
// }
}
Student2类
// final成员变量使用构造函数赋值的方式
public class Student2 {
private final String name;
// 因为final成员变量使用的构造函数赋值的方式
// 全部重载的构造函数都要对final修饰的成员变量进行赋值
public Student2() {
this.name = "范冰冰";
}
public Student2(String name) {
this.name = "范冰冰";
}
public String getName() {
return name;
}
// final修饰的成员变量么使用构造函数赋值,要么使用直接赋值的方式
// 所以final成员变量的setter方法不再需要
// public void setName(String name) {
// this.name = name;
// }
}