浅析Java中的final关键字(详细)

这篇具有很好参考价值的文章主要介绍了浅析Java中的final关键字(详细)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

1.什么是final关键字(概念)

2.final关键字基本用法

3.深入理解final关键字

4.final 关键字的最佳实践

什么是final关键字(概念)

谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字 。final 是 Java 中的一个关键字,可以用于修饰类、方法和变量。当一个类被声明为 final 时,它意味着该类不能被继承。当一个方法被声明为 final 时,它意味着该方法不能被重写。当一个变量被声明为 final 时,它意味着该变量的值不能被修改。

 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,但是final类中的所有成员方法都会被隐式地指定为final方法。 在使用final修饰类的时候,一定要谨慎选择,除非这个类以后不会用来继承或者出于安全考虑,尽量不要将类设计为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实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。“
因此,如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。即父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的。

final修饰的方法表示此方法已经是“最后的、最终的”含义,亦即此方法不能被重写(可以重载多个final修饰的方法)。此处需要注意的一点是:因为重写的前提是子类可以从父类中继承此方法,如果父类中final修饰的方法同时访问控制权限为private,将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同的方法名和参数,此时不再产生重写与final的矛盾,而是在子类中重新定义了新的方法。(注:类的private方法会隐式地被指定为final方法)

final修饰变量

final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;如果final修饰一个引用类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。本质上是一回事,因为引用的值是一个地址,final要求值,即地址的值不发生变化。
final修饰一个成员变量(属性),必须要显示初始化。这里有两种初始化方式,一种是在变量声明的时候初始化;第二种方法是在声明变量的时候不赋初值,但是要在这个变量所在的类的所有的构造函数中对这个变量赋初值。

class Animal {
    private final int count = 0;
    public Animal() {
        count = 1; //报错
        final Object object = new Object();
        object = new Object(); //报错
    }
}

深入理解final关键字 

类的final变量和普通变量的区别

当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。
那么final变量和普通变量到底有何区别呢?下面请看一个例子:

public class Test {
    public static void main(String[] args) {
        String a = "helloworld";
        final String b = "hello";
        String c = "hello";
        String x = b + "world";
        String y = c + "world";
        System.out.println(a == x);
        System.out.println(a == y);
    }
}

输出结果:true ; false

大家可以先想一下这道题的输出结果。为什么第一个比较结果为true,而第二个比较结果为fasle。这里面就是final变量和普通变量的区别了,当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。这种和C语言中的宏替换有点像。因此在上面的一段代码中,由于变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的值。而对于变量d的访问却需要在运行时通过链接来进行。想必其中的区别大家应该明白了,不过要注意,只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化,比如下面的这段代码就不会进行优化:

public class Test {
    public static void main(String[] args) {
        String a = "helloworld";
        final String b = getHello();
        String x = b + "world";
        System.out.println(a == x);
    }
    public static String getHello() {
        return "hello";
    }
}

这段代码的输出结果为false。这里要注意一点就是:不要以为某些数据是final就可以在编译期知道其值,通过变量b我们就知道了,在这里是使用getHello()方法对其进行初始化,他要在运行期才能知道其值。

被final修饰的引用变量指向的对象内容可变 

在上面提到被final修饰的引用变量一旦初始化赋值之后就不能再指向其他的对象,那么该引用变量指向的对象的内容可变吗?看下面这个例子:

public class Test {
    public static void main(String[] args) {
       final Object object = new Object();
        System.out.println(++object.i);
    }
}
class Object {
    public int i = 0;
}

输出结果: 1

这段代码可以顺利编译通过并且有输出结果,输出结果为1。这说明引用变量被final修饰之后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的。

 final参数的问题

在实际应用中,我们除了可以用final修饰成员变量、成员方法、类,还可以修饰参数、若某个参数被final修饰了,则代表了该参数是不可改变的。如果在方法中我们修改了该参数,则编译器会提示你:The final local variable i cannot be assigned. It must be blank and not using a compound assignment。看下面的例子:

public class TestFinal {
    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        int i = 0;
        testFinal.changeValue(i);
        System.out.println(i);
    }

    public void changeValue(final int i) {
        //final参数不可改变
        i++; //报错,因为参数i已经被final修饰了
        System.out.println(i);
    }
}

上面这段代码changeValue方法中的参数i用final修饰之后,就不能在方法中更改变量i的值了。值得注意的一点,方法changeValue和main方法中的变量i根本就不是一个变量,因为java参数传递采用的是值传递,对于基本类型的变量,相当于直接将变量进行了拷贝。所以即使没有final修饰的情况下,在方法内部改变了变量i的值也不会影响方法外的i。文章来源地址https://www.toymoban.com/news/detail-769482.html

到了这里,关于浅析Java中的final关键字(详细)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 浅析Java中volatile关键字

            Java中的volatile用于修饰一个变量,当这个变量被多个线程共享时,这个变量的值如果发生更新,每个线程都能获取到最新的值。volatile在多线程环境下还会禁止指令重排序,确保变量的赋值操作按照代码的顺序执行。需要注意是它不能保证变量操作的

    2024年01月21日
    浏览(48)
  • Java 基础进阶篇(三)—— 权限修饰符、final 关键字与枚举

    权限修饰符 用于约束成员变量、构造器、方法等的访问范围。 权限修饰符: 有四种作用范围由小到大 (private - 缺省 -protected - public) 注: 不同包下的子类指的是,不同包下的子类对象能访问,当前类创建父类对象访问不了。 定义成员变量、构造器、方法等一般需满足如下要

    2024年02月02日
    浏览(66)
  • 全面理解java中的构造方法以及this关键字的用法(超详细)

    Hello,各位铁汁们!我是小🐟儿哈!今天我又来更新我的Java基础学习博客了。 本篇主要内容概述: 1、🍚如何用构造方法初始化对象 2、🍚为啥要有this这个 3、🍚this.属性名访问成员变量、成员方法 4、🍚this.方法名 || this.()的用法 目录 初识构造方法  构造方法的使

    2023年04月09日
    浏览(62)
  • 【Java基础教程】(十四)面向对象篇 · 第八讲:多态性详解——向上及向下转型、关键字 final与 instanceof的作用~

    掌握final 的主要作用及使用; 掌握对象多态性的概念以及对象转型的操作; 掌握instanceof 的主要作用及使用; 在Java 中 final称为终结器,在Java 里面可以使用 final定义类、方法和属性,用于表示不可变性 。 final 类:当一个类被声明为 final 时,意味着该类不能被

    2024年02月16日
    浏览(53)
  • Java中的volatile关键字实现原理

    在并发编程中,线程之间的可见性问题是非常重要的一项难题。Java中提供了一种解决并发可见性问题的机制,即volatile。 在本文中,我们将会讲解Java中volatile的实现原理,为什么它能够保证可见性,以及背后的实现原理涉及到的内存屏障和JVM屏障等内容。在学习

    2023年04月27日
    浏览(42)
  • Java面试题:请谈谈Java中的volatile关键字?

    在Java中,volatile是一种特殊的修饰符,用于确保多线程环境下的变量 可见性和顺序性 。当一个变量被声明为volatile时,它可以确保以下两点: 内存可见性 :当一个线程修改了一个volatile变量的值,其他线程会立即看到这个改变。这是因为volatile会禁止CPU缓存和编

    2024年04月23日
    浏览(54)
  • Java中 private关键字 详细用法及解释

    ​ 出于 安全性考虑 ,我们在写字段时,尽量考虑采用 封装 ,这样可以隐藏类的细节,只对外开放接口即可实现对象之间的交互。 private是 一个 访问限定修饰符 可修饰的的范围: 修饰成员变量: 表示当前成员变量 只能在当前类中使用 修饰成员方法: 表示当前成员方法 只

    2024年02月03日
    浏览(54)
  • static关键字和final关键字

    在java的中,static和final是两个必须掌握的。static和final用法多样,且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。下面将依次介绍static和final。注意,某些场景下,staic和final可以联合使用

    2024年02月09日
    浏览(61)
  • final 关键字的用法

    final; //使用的位置: 1.用于声明常量:基本数据类型的常量不允许修改值,                            引用数据类型的常量不允许重新分配内存地址 2.用于声明方法(最终方法),该方法在了类中不能重写,在当前类中允许重载 3.用于声明类(最终类), 该类不允许子类继承

    2024年01月21日
    浏览(51)
  • final关键字的作用

    目录 1.修饰类时 2.修饰方法时 3.修饰属性和局部变量时 3.1修饰局部变量时 3.2修饰成员变量时 3.3修饰类变量时 4.final与普通变量的区别 5.final用于引用 1.只能是公共的(public)就算不写也是public 2.被final修饰的类不可以被继承 1.方法不能不能覆盖 2.被final修饰的方法,JVM会尝试

    2024年02月05日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包