- 说明
- Java中的关键字final通常是指“这是无法改变的”。一般使用final关键字有四种情况:变量、参数、方法、类。本文从这四个方面讲述final的用法。
- 参考资料《Java编程思想》。
- 例子
- final修饰变量
- final修饰基本类型变量
- 如果final修饰基本类型变量,则不能再对这个基本类型变量重新赋值,否则报错。
- 代码
1 public class Test {
2 public static void main(String[] args) {
3 final int a = 11;
4 int b = 111;
5 a = 123;//The final local variable a cannot be assigned. It must be blank and not using a compound assignment
6 a = b;//The final local variable a cannot be assigned. It must be blank and not using a compound assignment
7 System.out.println(a);
8 }
9
10 class Dog{
11 private final int age;
12
13 public Dog(int age){
14 this.age = age;
15 }
16
17 //The final local variable a cannot be assigned. It must be blank and not using a compound assignment
18 public void setAge(int age){
19 this.age = age;
20 }
21 //The final local variable a cannot be assigned. It must be blank and not using a compound assignment
22 public void ff(){
23 this.age = 12;
24 }
25 }
26 }
- View Code
- 分析
- main的final修饰的变量a在定义的时候就初始化了,编译时a的值就已经确定了,不能修改,否则报错。
- Dog类中final修饰的变量age在定义的时候没有初始化,因此在编译期间是无法确定值的,只有创建Dog对象调用其构造方法的时候才可以确定。但是一旦初始化就不可更改,因此setAge方法和ff方法都试图再次对其赋值是错误的。
- 结论
- final修饰基本类型变量,不论是在定义时初始化,还是通过构造方法初始化,一旦初始化之后就不可更改。
- 另外,如果一个变量同时被final和static修饰,一般用大写表示,使用下划线分隔单词。
- final修饰引用类型变量
- 代码
- Cat类代码
1 public class Cat {
2
3 private String name;
4
5 public String getName() {
6 return name;
7 }
8
9 public void setName(String name) {
10 this.name = name;
11 }
12
13 public Cat(String name) {
14 super();
15 this.name = name;
16 }
17 }
- View Code
- Test类代码
1 public class Test {
2 public static void main(String[] args) {
3 final Cat c1 = new Cat("大黄");
4 System.out.println(c1.getName());
5 System.out.println(c1);
6 c1.setName("老铁");
7 System.out.println(c1.getName());
8 System.out.println(c1);
9 }
10 }
- View Code
- 运行结果如下图
- 分析
- 形象的说就是,我买了个猫放在家里,并给他起名为大黄,这时,我们可以知道这个猫在我家(地址是xxx市xxx区xxx街道),猫的名字叫大黄。然后我把猫的名字改为“老铁”,这时这个猫依然在我家(地址是xxx市xxx区xxx街道),但是名字却变了。名字变了还是我家的猫啊,我还是它的铲屎官啊。
- 从上面的截图也可以看出,c1变量虽然被final修饰了,但是依然可以改变c1所引用的对象(name改了)。
- 上面截图的@后面的东西是c1变量在内存中的地址,可以看出改变名字前后,c1的引用的地址没变。
- 结论
- final修饰引用类型变量表示这个变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变(如某个属性的值)。
- fianl修饰参数
- 测试类代码
1 public class Test {
2 public static void main(String[] args) {
3 print1(11);
4 Cat c = new Cat("大黄");
5 print2(c);
6 }
7
8 static void print1(final int age){
9 age = 11;//The final local variable age cannot be assigned. It must be blank and not using a compound assignment
10 System.out.println(age);
11 }
12
13 static void print2(final Cat c){
14 c = new Cat("haha");//The final local variable age cannot be assigned. It must be blank and not using a compound assignment
15 c.setName("yaoyao");
16 }
17 }
- View Code
- 分析
- print1方法的参数age是被final修饰的基本类型,通过上面的代码可以看出,当我们在方法中试图再次对其赋值时,报错。说明final修饰基本类型参数表示这个参数在该方法中不可以修改。
- print2方法的参数c是被final修饰的引用类型,通过上面的代码可以看出,当我们在方法中试图再次对其赋值时,也报错。但是我们却可以设置c的名字。说明final修饰引用类型的参数表示在方法中这个参数的引用不可改变,但是这个对象可以改变。
- 结论
- final修饰基本类型参数表示这个参数在该方法中不可以修改,就是不能再次赋值。
- final修饰引用类型参数表示在方法中这个参数的引用不可改变,但是这个对象可以改变。
- final修饰方法
- 代码
1 public class Test {
2 public static void main(String[] args) {
3
4 }
5
6 class Person{
7 final void test(){
8 System.out.println("别摸我");
9 }
10
11 void test(String name){
12 System.out.println(name);
13 }
14 }
15
16 class Student extends Person{
17 //Cannot override the final method from Test.Person
18 void test(){
19
20 }
21
22 void test(String name){
23 System.out.println(name);
24 }
25
26 void print(){
27 super.test();
28 }
29 }
30 }
- View Code
- 分析
- Person是父类。Student继承了Person类,是子类。
- Person类有一个被final修饰的方法test(),还有一个重载方法test(String name),这两个方法都没有语法错误。
- Student类有一个test(String name)方法,重写了父类的test(String name)方法,没有问题。但是另一个方法test()重写父类的被final修饰的test()方法时,却报错了。说明被final修饰的方法不能被子类重写。另外print()方法中调用了父类Person中的被final修饰的test()方法,也没有问题,说明子类可以使用父类中被final修饰的方法。
- 结论
- 当final修饰一个方法时,该方法不能被子类重写,但是子类可以使用父类的这个方法。
- 当final修饰一个方法时,本类可以重载被final修饰的方法。
- final修饰类
- 代码
1 public class Test {
2 public static void main(String[] args) {
3 print();
4 }
5
6 static void print(){
7 Person p = new Person("jack");
8 System.out.println(p.getName());
9 p.setName("yaya");
10
11 System.out.println(p.getName());
12 }
13
14 }
15
16 final class Person{
17 String name;
18
19 public Person(String name) {
20 super();
21 this.name = name;
22 }
23
24 public String getName() {
25 return name;
26 }
27
28 public void setName(String name) {
29 this.name = name;
30 }
31 }
32
33 //The type Student cannot subclass the final class Test.Person
34 class Student extends Person{
35
36 }
- View Code
- 分析
- Person类是一个被final修饰的类,Student类打算继承Person类,但是报错,说明被final修饰的被不能被继承,当然方法也不能重写(不继承怎么重写)。
- print()方法显示创建一个Person对象,且name是jack,然后修改name为yaya,没有错误。说明被final修饰的类的成员变量是可以修改的。
- 结论
- 当final修饰一个类时,这个类不能被继承,但是其成员变量可以被修改。
- 总结
- final修饰变量
- final修饰基本类型变量,则该变量一个被初始化就不可被修改。
- final修饰引用类型变量,则该变量的引用不可被更改,但是该引用指向的对象可以被修改。
- final修饰参数
- final修饰的参数是基本类型,则该参数在方法中不可被修改。
- final修饰的参数是引用类型,则该参数引用不可被修改,但是该引用指向的对象可以被修改。
- final修饰方法
- final修饰的方法不可以被子类重写,但是子类可以使用这个方法。
- final修饰的方法可以被重载。
- fianl修饰类
- final修饰的类不可以被继承,但是其成员变量可以被修改。