1. Final介绍
final 中文意思是最后的,最终的。
final可以修饰类、属性、方法和局部变量。
在某些情况下,程序员可能有一下需求,就会使用到final
2. final 修饰类
使用 final 修饰类表示该类不能被继承。也就是说,final 类是最终的、不可改变的类。当一个类被 final 修饰时,它的所有成员方法也被隐式地指定为 final 方法,不能被子类重写。
final 类通常用于设计不可变类或者安全类,以防止子类继承和篡改。它还可以用于提高代码性能,因为编译器在编译时可以对 final 类进行优化。
使用 final 修饰的类不能被继承,但它仍然可以包含其他类所拥有的成员变量和成员方法。同时,final 修饰符还可以用于修饰类中的成员变量和成员方法,表示它们只能被初始化一次或者只能被调用一次。
需要注意的是,final 类并不一定就是最好的选择。使用 final 修饰类会使得该类不能被继承,这可能会限制代码的扩展性和灵活性。因此,在选择是否使用 final 修饰类时,需要根据具体的应用场景来综合考虑。
// 1.当不希望类被继承时,可以使用 final 修饰类,这样他就不能被其他类继承
final class Animal01{}
// 报错,使用 final 修饰的类无法被继承
class Dog01 extends Animal01{} // 报错!!!
3. final 修饰方法
使用 final 修饰方法表示该方法不能被子类重写。当一个方法被 final 修饰时,它不能被子类重写或者覆盖。
final 方法通常用于设计不可变类或者安全类,以防止子类重写某些关键方法。同时,final 方法还可以用于提高代码性能,因为编译器在编译时可以对 final 方法进行优化,从而减少程序的运行开销。
需要注意的是,final 方法只能被子类继承和调用,不能被子类重写。因此,当一个方法被 final 修饰时,应该仔细考虑其对代码的影响,以免影响代码的可维护性和扩展性。
class Animal01{
// 2. 如果不该希望方法被重写或覆盖可以使用 final 修饰
public final void say(){
}
}
class Dog01 extends Animal01{
// 这时子类无法重写父类的 final 方法
@Override
public void say() { //报错,使用 final 修饰的方法无法被重写
System.out.println("重写父类方法");
}
}
4. final 修饰属性
使用 final 修饰属性表示该属性只能被赋值一次,赋值后不能再次修改。当一个属性被 final 修饰时,它可以在构造方法中或者属性声明时进行初始化,并且在对象创建后不能再被修改。
final 属性通常用于设计不可变类或者安全类,以保证类的属性不会被篡改。同时,final 属性还可以用于提高代码的可读性和可维护性,因为它们不能被修改,因此可以提供更好的代码清晰度。
需要注意的是,final 属性只能被初始化一次,因此必须在声明时或者构造方法中初始化。如果 final 属性是一个对象类型,则其引用可以被修改,但是其所指向的对象不能被修改。
使用 final 修饰属性可以提高代码的可读性、可维护性和安全性,但是需要注意其在构造方法中的初始化顺序和规范使用。
class Animal01{
// 3. 如果不该希望属性值被修改,可以使用 final 修饰
public final int age = 2;
}
public class Final01 {
public static void main(String[] args) {
Animal01 animal = new Animal01();
animal.age = 10; //报错 ,使用 final 修饰的属性无法被修改
}
}
- 当不希望某个局部变量的值被修改时,可以使用final修饰该局部变量
public class Final01 {
public static void main(String[] args) {
// 4. 如果不希望局部变量的值被修改时,可以使用final修饰该局部变量量
final float pi = 3.14f;
pi = 4.1415; // 报错,使用 final 修饰的局部变量无法被修改
}
}
5. final 修饰静态属性
使用 final 修饰静态属性表示该属性只能被赋值一次,赋值后不能再次修改。当一个静态属性被 final 修饰时,它可以在静态代码块中或者属性声明时进行初始化,并且在类加载后不能再被修改。
final 静态属性通常用于设计常量,以保证它们的值不会被篡改。同时,final 静态属性还可以用于提高代码的可读性和可维护性,因为它们不能被修改,因此可以提供更好的代码清晰度。
需要注意的是,final 静态属性只能被初始化一次,因此必须在声明时或者静态代码块中初始化。如果 final 静态属性是一个对象类型,则其引用可以被修改,但是其所指向的对象不能被修改。
使用 final 修饰静态属性可以提高代码的可读性、可维护性和安全性,但是需要注意其在静态代码块中的初始化顺序和规范使用。
- final 修饰情态属性初始化的位置:
- 定义时现显式的赋值
- 静态代码块中显式的赋值
- 注意:不能 在构造器中赋值
public class Final03 {
// 如果 final 修饰的属性时静态的, 则初始化可以在如下两个位置之一
// 1. 定义时显式的赋值
final static String FINAL_NAME_ONE = "final.name.1";
final static String FINAL_NAME_TWO; //
static {
// 2. 在代码块中赋值
FINAL_NAME_TWO = "final.name.2";
}
// 注意: 如果 final 修饰的属性时静态的 不能 在构造器中赋值
final static String FINAL_NAME_THREE;
public Final03(){
FINAL_NAME_THREE = "final.name.3";
}
}
6. final 使用注意事项和细节讨论
final 修饰的属性又叫常量,一般使用 XXX_XXX_XXX来命名
final 修饰的属性在定义时,必须赋予初始值,并且以后不能在修改, 赋值可以在如下三个位置之一(选择一个位置赋初始值即可)
- 定义时显式的赋值(优先级最高): 如
public final int a = 10;
- 在代码块中赋值(优先级中)
- 在构造器中赋值(优先级低)
- 定义时显式的赋值(优先级最高): 如
public class Final02 {
// 1. final修饰的属性又叫常量,一般使用 XXX_XXX_XXX来命名
// 2. final 修饰的属性在定义时,必须赋予初始值,并且以后不能在修改
// 2.1 定义时显式的赋值
final String FINAL_NAME_ONE = "final.name.1";
final String FINAL_NAME_TWO; //
final String FINAL_NAME_THREE; //
{
// 2.2 在代码块中赋值
FINAL_NAME_TWO = "final.name.2";
//因为在常量在定义时已经赋值了,不能对其值进行修改
// FINAL_NAME_ONE = "final.name.1";
}
public Final02(){
// 2.3 在构造器中赋值
FINAL_NAME_THREE = "final.name.3";
}
}
- final类不能被继承,但是可以被实例化,final类中的属性也可以被修改
public class Final04_finalclass {
public static void main(String[] args) {
// final 修饰的类可以被实例化
Animal04 animal = new Animal04();
// final 修饰的类里的属性也可以被修改
animal.a = 100;
System.out.println(animal.a);
}
}
// 被final 修饰的类不能被继承
// class Dog extends Animal04{ }
final class Animal04{
int a = 10;
}
- 如果类不是final类, 但是含有final方法, 则该方法虽然不能被重写, 但是依然可以被继承
public class Final05_finalclass {
public static void main(String[] args) {
Dog05 dog = new Dog05();
dog.say(); // hello
Animal05 animal = new Animal05();
animal.say(); // hello
}
}
class Dog05 extends Animal05{
// final修饰的方法不能被重写
// public void say(){
// System.out.println("wang!wang~wang~");
// }
}
class Animal05{
// final 修饰了类中的某个方法,类依然可以被继承, 但是该方法不能被重写
public final void say(){
System.out.println("hello");
}
}
- 一般来说, 如果一类是final修饰的类, 那么就没有必要再使用final修饰该类中的方法了
- final不能修饰构造方法
- final 和 static 往往搭配使用,因为底层编译做了优化处理,不会导致类加载, 所以效率更高
- 包装类(Integer、Double、Float)等都是 final 类,String 也是 final 类