【Java关键字】理解final关键字

前言

我们在了解final关键字之前,可以先从它的字面意思去理解,有道翻译查询如下:
在这里插入图片描述
也就是说,final的中文意思就是最终的、不可改变的。在Java中,final关键字表达的也是这样的意思。final关键字修饰变量、方法和类,不管修饰什么,其本意都是指“它是无法更改的”。本文将介绍final关键字:

  • final关键字修饰变量
  • final关键字修饰方法参数
  • final关键字修饰方法
  • final关键字修饰类

(若文章有不正之处,或难以理解的地方,请多多谅解,欢迎指正)

final关键字修饰变量

只要是被final修饰的成员变量或本地变量(在方法中或在代码块中的变量称为本地变量)都称为final变量,final变量经常和static关键字一起使用,作为常量。用final关键字修饰的变量,只能进行一次赋值操作,并且生存期间不可以改变其值。

不过final关键字在基本数据类型和引用类型产生的效果还是有点区别。举个栗子:

public class Cats {
    public static void main(String[] args){
        final int catNum = 6;
        final Cat c = new Cat("black");
        catNum = 5;  //Cannot assign a value to final variable 'catNum'
        c.color = "white";  //正常执行
        c = new Cat("brown");  //Cannot assign a value to final variable 'c'
    }
}
class Cat{
    String color;
    public Cat(String color){
        this.color = color;
    }
}

从上述代码可以看出,final关键字对于基本数据类型和引用类型的效果是一样的:只能进行一次赋值操作,并且生存期间不可以改变其值。而且,虽然final关键字限制引用类型的引用地址,但并不会对引用类型的内部属性进行限制,所以c.color = "brown"是可以正常执行的。

final关键字修饰方法参数

上文提到,final关键字修饰变量时,该变量只能进行一次赋值操作,且不能改变其值。如果变量是作为参数传入的,那么我们怎么保证它的值不会改变呢?这就用到了final的第二个用法。

public static void print(final int i, final Date date){
        i = 1;  //Cannot assign a value to final variable 'i'
        date = new Date();  //Cannot assign a value to final variable 'date'
        System.out.println(i);
    }

可以看到,如果我们不希望传入的参数在方法中被改变,可以在方法签名中声明该参数被final关键字修饰

final关键字修饰方法

如果你认为一个方法的功能已经足够完整了,在方法前面声明final,代表这个方法不可以被子类的方法重写。因为final方法在编译的时候就已经静态绑定了,不需要运行时再动态绑定,所以final方法比非final方法要快一点

class BlackCat extends Cat{
    public String getColor(){
        //'getColor()' cannot override 'getColor()' in 'Cat'; overridden method is final
    }
}
class Cat{
    private String color = "white";
    final public String getColor(){
        return color;
    }
}

那么“在开发过程中,private修饰方法隐式等同于使用final修饰“,这是真的吗?举个栗子:

在使用final修饰方法时,子类方法是不能复写父类中用final修饰的方法:

public class Cat{
    final void meow(){}
}
class BlackCat extends Cat{
    void meow(){}  //'meow()' cannot override 'meow()' in 'Cat'; overridden method is final
}

而使用private修饰方法时,虽然子类中可以存在于父类同名的private方法,但这个方法却不是从父类那里继承过来的了:

public class Cat{
    private void meow(){}
}
class BlackCat extends Cat{
    @Override //Method does not override method from its superclass
    private void meow(){}
}

但是如果直接说,“private修饰方法等同于使用final修饰“,笔者不太认同,举个栗子:

public class Cat{
    private void getColor(){}
    private final void getFood(){}
    final void getOwner(){}
}

我们进行编译之后,使用idea的插件jclasslib Bytecode Viewer查看Cat类的字节码,我们可以通过class文件中,专门描述方法的方法表的访问标志access_flags来判断:

首先是private void getColor()方法:
在这里插入图片描述
此次是private final void getFood()方法:
在这里插入图片描述
最后是final void getOwner()方法:
在这里插入图片描述
总结一下,所有final关键字只有明确禁止重写方法的时候,才使用其修饰方法

final关键字修饰类

final关键字修饰类,表示这个类不可以被继承。所以如果不希望某个类有子类,就可以用final关键字来修饰。并且由于是用final关键字修饰的类,其类中的方法也会被隐式只为final方法

在JDK中有很多类是final关键字修饰的,如String、Integer等。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {

结语

本文主要对final关键字进行介绍,如果本文对你有帮助,请给一个赞吧,这会是我最大的动力~

【Java关键字】系列还有这些文章哦:

【Java关键字】理解static关键字

【Java关键字】理解instanceof关键字

你真的有好好了解过序列化吗:Java序列化实现的原理

参考资料:

Java关键字(四)——final

Java中final关键字详解

posted @ 2020-04-17 13:44  NYfor2018  阅读(320)  评论(0编辑  收藏  举报