一. 概述
final关键字代表最终,不可改变的.
常见有5种用法,我们来归纳总结一下:
1. 用来修饰一个类
2. 用来修饰一个方法
3. 用来修饰成员变量
4. 用来修饰局部变量
5. 用来修饰方法参数
二. final饰修类
如果声明一个类为final类, 那么这个类就是最终类,不能被继承
public final class ParentClass {
    public void happy() {
        System.out.println("高兴");
    }
} 
当写一个类去继承它的时候
public class ChildClass extends ParentClass{
} 
就会提示如下错误:

注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写.
三. final修饰方法
当final用来修饰一个方法的时候,这个方法就是最终方法,那么很明显就是说不能被覆盖重写。
public class ParentClass {
    public void happy() {
        System.out.println("高兴");
    }
    
    //用final关键字修饰的方法
    protected final void play(){
        System.out.println("开心的玩耍");
    }
}
 
我们在继承类中去看下 play()方法是否可以被override

也是报错,说明 final修饰的方法,是一个最终方法,不能被子类去覆盖重写.
四. final修饰成员变量
在java中,成员变量一般都有默认值, 比如 int 型变量,默认值为0 boolean型变量默认值为false
String型变量,默认值为null

我们来看上面的例子, 3个同样类型的 int型 成员变量, number temp 默认值都是0 , 写和没写都没有报错. 但是加上final之后的num变量,没有初始化就报错.
总结一: 由于成员变量具有默认值,但是用了final关键字修饰之后必须要手动赋值初始化值.
我们在看一个例子

总结二: 对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可被改变。
五. final修饰局部变量
对于基本类型来说,不可变说的是变量当中的数据不可改变;
 
请看如下例子:

对于引用类型来说,不可变指的是变量当中的地址值不可改变 
我们再来看下个例子,
Student为一个普通的javabean类
public class Student {
 
    private String name;
 
    public Student() {
    }
 
    public Student(String name) {
        this.name = name;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
} 
第一种情况,没有final修饰的测试类
public class FinalVarTest {
    public static void main(String[] args) {
        Student student1 = new Student("勒布朗.詹姆斯");
        System.out.println(student1); //打印内存地址
        System.out.println(student1.getName());
        student1 = new Student("斯蒂芬.库里");
        System.out.println(student1); //打印内存地址
        System.out.println(student1.getName());
    }
}
 
打印结果如下:
com.finaltest.Student@4aa298b7   //内存地址
勒布朗.詹姆斯
com.finaltest.Student@7d4991ad  //内存地址
斯蒂芬.库里 
输出结果:内存地址不同
第二种情况: 使用final修饰测试类

若用final修饰,地址值不可以被改变,否则直接报错.
地址值虽然不能变,但是内容可以变(地址所指向的对象的属性可以被该变)。
请看如下例子:
public class FinalVarTest {
    public static void main(String[] args) {
        //使用final修饰的对象
        final Student student2 = new Student("詹姆斯.哈登");
        System.out.println(student2); //打印内存地址
        System.out.println(student2.getName());
        student2.setName("安东尼.戴维斯");
        System.out.println(student2); //打印内存地址
        System.out.println(student2.getName());
    }
} 
打印结果如下:
com.finaltest.Student@4aa298b7
詹姆斯.哈登
com.finaltest.Student@4aa298b7
安东尼.戴维斯
 
两者的内存地址是相同的,但是名字(属性)是可以修改的.
六. final修饰参数
在方法参数前面加final关键字就是为了防止数据在方法体中被修改。
主要分两种情况:第一,用final修饰基本数据类型;第二,用final修饰引用类型。
第一种情况,修饰基本类型(非引用类型)。这时参数的值在方法体内是不能被修改的,即不能被重新赋值。否则编译就通不过。例如:

第二种情况,修饰引用类型。这时参数变量所引用的对象是不能被改变的。作为引用的拷贝,参数在方法体里面不能再引用新的对象。否则编译通不过。例如:

但是对于引用,如果我是这样(也就是引用对象的地址不能改变,但是对象中的内容是可以改变的),则不会报任何错,完全能编译通过。
public class FinalVarTest {
    public static void main(String[] args) {
        String[] var = {"张三","李四", "王五"};
        valid(var);
    }
    public static void valid(final String[] ag){
       ag[2]= "赵六";
       for(int i=0; i<ag.length; i++) {
           System.out.println(ag[i]);
       }
    }
} 
编译通过,打印如下:
张三
李四
赵六 
                


















