前置知识
final 在 Java 中是关键字之一,意为最终,表示对象或数据是最终形态的、不可改变的意思,它可以修饰 类、变量、方法。使用 final 修饰的 类、方法、变量具有如下特点
- final 修饰的类不能被继承
- final 修饰的方法不能被子类重写
- final 修饰的成员变量或局部变量(即常量),只能赋值一次,不能重复赋值
- final 修饰的成员变量须在声明时赋值,如果在声明时未赋值,必须在构造方法中显式赋值才能使用
- final 修饰的局部变量可以只声明不赋值,但必须在使用前进行赋值
final 关键字深入使用理解
final 变量
- 如果 final 修饰的是一个基本数据类型的变量,则其数值一旦在初始化之后就不能更改
- 如果 final 修饰的是一个引用类型的变量,则对其初始化之后就不能再将其指向另一个对象,但该实例对象的实例变量可以修改值
- 匿名内部类不能访问外部类方法中的局部变量,
除非该变量被声明为final类型
public class TestMain {
public static final int a = 10;
public static void main(String[] args) {
final int b = 11;
//以下两行代码均报错,不能为 final 修饰的常量重复赋值
//a = 11;
//b = 12;
final String[] str = {"a","b","c"};
System.out.println(Arrays.toString(str));//输出 [a, b, c]
str[0] = "d";
System.out.println(Arrays.toString(str));//输出 [d, b, c]
final Student student = new Student("001");
System.out.println(student);//输出 Student(id=001)
student.setId("002");
System.out.println(student);//输出 Student(id=002)
//student = new Student("003");//无法为最终变量 student 重新分配引用地址
}
/**在内部类的方法使用到方法中定义的局部变量,则该局部变量需要添加 final 修饰符*/
public void test(){
//此处在Java8里 final不用写,但其实是 final 的,看字节码文件便知
final int number = 123;
InnerClass innerClass = () -> System.out.println(number);
innerClass.show();
}
/**在内部类的方法形参使用到外部传过来的变量,则形参需要添加 final 修饰符*/
public void test(final String str){
InnerClass innerClass = () -> System.out.println(str);
innerClass.show();
}
}
interface InnerClass {
void show();
}
@Data
@AllArgsConstructor
class Student{
private String id;
}
-
final 成员变量必须满足以下其中一个条件(使用前必须要赋值)
-
在构造函数中赋值
-
初始化赋值(直接赋值或者初始化块中赋值)
-
/*常量在声明时初始化*/
public final int num1 = 123;
------------------------------------------------------
/*常量在初始化块中初始化*/
public final int num2;
{
num2 = 123;
}
------------------------------------------------------
/*常量在构造函数中初始化*/
public final int num3;
public Constructor(int num){
this.num3 = num;
/*重复的给常量初始化会报错*/
//this.num1 = 123;
}
------------------------------------------------------
/*静态常量在声明时初始化*/
public static final int num4 = 123;
------------------------------------------------------
/*静态常量在静态代码块中初始化,不能在初始化块中初始化*/
public static final int num5;
static {
num5 = 123;
}
final 类
当用 final 修饰一个类时,表明这个类不能被继承。final 类中的所有成员方法都会被隐式地指定为 final 方法。例如 final 在 String、StringBuffer、StringBuilder 中都修饰类,其中在 String 类中的静态内部类中为了防止修改应用而大量使用 final 修饰局部变量
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
public int indexOf(int ch, int fromIndex) {
final int max = value.length;
...........
}
}
final 方法
使用 final 方法的原因
-
防篡改。以防任何继承类修改它的含义
-
效率。在早期的 Java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的 Java 版本已经不需要使用 final 方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final
public class Parent {
public final void show(){
System.out.println("parent");
}
}
public class Children extends Parent{
//此处重写父类的final方法报错
/*@Override
public void show() {
super.show();
}*/
}
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/272125.html