一.修饰类
final用来修饰类的时候,这个类就不可以被继承,俗称“太监类”,什么意思呢?就是说这个类不能再有子类,但是对于他继承于父类是不会有影响的,他依然可以覆盖重写父类方法,类似于古代的太监虽然香火断了,但是父亲还是存在的。
//我们姑且用Fu类-->Zi类-->Sun类
public class Fu {}
//final修饰Zi类,但是依然可以继承于Fu类
public final class Zi extends Fu { }
//下面的用法是错误的,因为Zi类用final来修饰,那么就不可以被继承
错误的用法:public class Sun extends Zi{ }
二.修饰方法
final修饰方法,那么该方法就不可以被覆盖重写,即父类中的final方法,在子类中不可以重写内容。
//父类
public class Fu {
public final void method(){
System.out.println("fu");
}
}
//子类
public class Zi extends Fu {
//不可以再覆盖重写method()方法
}
注意:不能和abstract同时使用 ,abstract抽象方法一定覆盖重写 ,而final一定不能覆盖重写,自相矛盾
三.修饰变量
1.成员变量
final修饰成员变量时,只可以赋值一次,以后不可以再赋值改变。一次赋值,终生不变。接下来我们说几种常见的情况:
直接赋值
首先来说,对于成员变量,即便是没有初始化,也是有默认值的,比如int的0,还有String的null等等,但是如果加了final,那么默认值就会去掉,也就是变量没有值了,那么显然是会报错的,所以,我们需要再后面直接加上默认值。
public class Person {
private final String name = "星爷";
public Person() {
}
public String getName() {
return name;
}
}
这里可以看到我并没有写有参构造方法,以及setName方法,为什么呢?这就得说咱们的final的含义了,一次赋值,终生不变,那么有参构造或者是无参构造,以及set方法但凡涉及到成员变量的改动就不可以出现。
构造方法赋值
public class Person {
private final String name;
public Person() {
this.name="星爷";
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
这里可以看到再无参构造中我们设置了成员变量的初始值,因为final会去掉其默认值,在有参构造我们可以通过new一个对象来初始化成员变量,所以这两个都可以完成成员变量的初始化,所以都是正确的,同样我们也没有设置set方法,因为对象创建的时候调用完构造函数就已经为成员变量赋值了,之后的set会改变其值,也就不符合final修饰成员变量时候的不可改变属性。
2.局部变量
引用类型
final修饰引用类型时,说明改局部变量的地址不可以改变,也就是说我们可以改变其中的数据的值,但是不可以更改其地址,该名称不可以重新new一个对象。
//正常情况下,我们可以重新new一个对象,但是其地址值改变了
Student student = new Student("星爷");
System.out.println(student);
student = new Student("发哥");
System.out.println(student);
输出结果为:
demo03.Student@b4c966a
demo03.Student@2f4d3709
其中的地址值发生了改变,那么当我们加上final的时候这种用法就是错误的了,所以不可以在new一个对象,但是我们可以改变其中的值,如下:
final Student student1 = new Student("华仔");
student1.setName("花花");
//下面是错误用法:
studen1 = new Student("错误用法");//地址改变,错误
基本类型
final修饰基本类型,同样是一次赋值,终生不变。主要是以下两种情况:
//第一种情况:
final int num2 = 200;//一次赋值,终生不变
//第二种情况:
final int num3;//没有进行一次赋值,所以下面可以赋值一次
num3 = 100;