final 关键字

1、final 可以修饰类、属性、方法、局部变量

2、作用

(1)类不能被继承

(2)父类方法不能被子类重写

(3)属性不能被修改

(4)局部变量不能被修改

4、普通常量赋值位置

(1)定义时

(2)构造器中

(3)代码块中

5、静态常量赋值位置

(1)定义时

(2)静态代码块中

6、非 final 类中含有 final 方法,该方法不能被重写,但可以被继承

7、包装类、String 类都是 final 类

 

final 数据

1、应用场景

(1)它可以是一个永远不会改变的编译时常量

(2)它可以是在运行时初始化的值,而你不希望它被更改、

2、不可变性

(1)对于基本类型,final 使其值恒定不变

(2)对于对象引用,final 使引用恒定不变,一旦引用被初始化为一个对象,它就永远不能被更改为指向另一个对象了,但是,对象本身是可以修改的

(3)Java 没有提供使对象恒定不变的方法,但是可以编写类,使对象具有恒定不变的效果,这个限制同样适用于数组,它们也是对象

3、编译时常量

(1)对编译时常量来说,编译器可以将常量值“折叠”到计算中,计算可以在编译时进行,这节省了一些运行时开销,这不仅确定值,还确定了值的类型

(2)在 Java 里,这些常量必须是基本类型,并用 final 关键字表示

(3)在定义常量时必须提供一个值

(4)一个既是 static 又是 final 的字段只会分配一块不能改变的存储空间

(5)按照惯例,具有常量初始值的 final static 基本类型(即编译时常量)全部使用大写字母命名,单词之间用下划线分隔

4、即使某字段是 final 的,也并不意味着它的值在编译时就是已知的,比如在运行时使用随机生成的数值来初始化

(1)static final:在加载时初始化一次

(2)final:每次创建新对象时都初始化该字段

5、空白 final

(1)空白 final 是没有初始值的 final 字段

(2)编译器会确保在使用前初始化这个空白 final 字段,否则无法通过编译

(3)这样类中的 final 字段就可以对每个对象来说都不同,同时还保持了其不可变的特性

(4)保证 final 字段在使用前总是被初始化,对 final 执行赋值的操作只能发生在:字段定义处使用表达式进行赋值 / 构造器 / 代码块 / 静态代码块

6、final 参数

(1)可以通过在参数列表中进行声明来创建 final 参数

(2)这意味着在方法内部不能更改参数引用指向的内容,可以读取这个参数,但不能修改它

(3)主要用于将数据传递给匿名内部类

 

final 方法

1、第一个使用原因是在方法上放置一个“锁”

(1)可以防止继承类通过重写来改变该方法的含义

(2)这样做一般是出于设计原因,比如想要确保在继承期间使方法的行为保持不变

2、第二个使用原因是效率

(1)在 Java 的早期实现中,如果创建了一个 final 方法 ,编译器可以将任何对该方法的调用转换为内联调用(inline call)

(2)当编译器看到 final 方法调用时,它可以(自行决定)跳过正常的方法调用方式,通过复制方法体中实际代码的副本来代替方法调用,这节省了方法调用的开销

(3)而正常的方法调用方式则是插入代码来执行方法调用的机制(将参数压入栈,跳到方法代码处并执行,然后跳回并清除栈上的参数,最后处理返回值)

(4)如果一个方法很大,这种内联方式就会让代码开始膨胀,可能不会看到内联带来的性能提升,因为调用和返回中的任何速度提升,都可能被在方法内花费的时间所抵消

(5)在相对较早的时候,JVM(特别是 hotspot 相关技术)就开始检测这些情况,并会优化掉额外的间接访问

(6)长期以来,Java 都不鼓励使用 final 来进行优化,应该让编译器和 JVM 来处理效率问题,只有在想明确防止重写的情况下才创建一个 final 方法

3、final 和 private

(1)类中的任何 private 方法都是隐式的 final,这是因为不能访问一个 private 方法,也不能重写它

(2)可以将 final 修饰符添加到 private 方法中,但它不会赋予该方法任何额外的意义

(3)这可能会令人困惑,因为如果尝试重写 private 方法(隐含是 final 的),似乎是可以的,并且编译器也不会给出错误消息

(4)“重写”只有在方法是基类接口的一部分时才会发生。即必须能将一个对象向上转型为其基类类型并能调用与其相同的方法。如果一个方法是 private 的,它就不是基类接口的一部分。它只是隐藏在类中的代码,只不过恰好具有相同的名称而已。即使在子类中创建了具有相同名称的 public、protected 或包访问权限的方法,它与基类中这个相同名称的方法也没有任何联系。并没有重写该方法,只不过是创建了一个新的方法。private 方法是不可访问的,并且可以有效地隐藏自己,因此除了定义它的类的代码组织之外,它不会影响任何事情

 

final 类

1、将整个类定义为 final 时(通过在其定义前加上 final 关键字),就阻止了该类的所有继承

2、原因

(1)希望对这个类的设计永远不要被修改

(2)出于安全考虑,不希望它有子类

3、final 类的字段可以是 final,也可以不是,根据个人选择而定

(1)无论类是否定义为 final,相同的规则都适用于字段的 final 定义

(2)由于 final 类禁止继承,它的所有方法都是隐式 final 的,因为无法重写它们

(3)可以在 final 类的方法中包含 final修饰符,但它不会添加任何意义

posted @   半条咸鱼  阅读(79)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示