Java final修饰符详解

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

final 在 Java 中的意思是最终,也可以称为完结器,表示对象是最终形态的,不可改变的意思。final 应用于类、方法和变量时意义是不同的,但本质是一样的,都表示不可改变,类似 C# 里的 sealed 关键字。

使用 final 关键字声明类、变量和方法需要注意以下几点:
final 用在变量的前面表示变量的值不可以改变,此时该变量可以被称为常量。
final 用在方法的前面表示方法不可以被重写(子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写,又称为方法覆盖。这里了解即可,教程后面我们会详细讲解)。
final 用在类的前面表示该类不能有子类,即该类不可以被继承。
final 修饰变量
final 修饰的变量即成为常量,只能赋值一次,但是 final 所修饰局部变量和成员变量有所不同。
final 修饰的局部变量必须使用之前被赋值一次才能使用。
final 修饰的成员变量在声明时没有赋值的叫“空白 final 变量”。空白 final 变量必须在构造方法或静态代码块中初始化。
注意:final 修饰的变量不能被赋值这种说法是错误的,严格的说法是,final 修饰的变量不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值。

public class FinalDemo {
void doSomething() {
// 没有在声明的同时赋值
final int e;
// 只能赋值一次
e = 100;
System.out.print(e);
// 声明的同时赋值
final int f = 200;
}
// 实例常量
final int a = 5; // 直接赋值
final int b; // 空白final变量
// 静态常量
final static int c = 12;// 直接赋值
final static int d; // 空白final变量
// 静态代码块
static {
// 初始化静态变量
d = 32;
}
// 构造方法
FinalDemo() {
// 初始化实例变量
b = 3;
// 第二次赋值,会发生编译错误
// b = 4;
}
}
上述代码第 4 行和第 6 行是声明局部常量,其中第 4 行只是声明没有赋值,但必须在使用之前赋值(见代码第 6 行),其实局部常量最好在声明的同时初始化。代码第 13、14、16 和 17 行都声明成员常量。代码第 13 和 14 行是实例常量,如果是空白 final 变量(见代码第 14 行),则需要在构造方法中初始化(见代码第 27 行)。代码第 16 和 17 行是静态常量,如果是空白 final 变量(见代码第 17 行),则需要在静态代码块中初始化(见代码第 21 行)。

另外,无论是那种常量只能赋值一次,见代码第 29 行为 b 常量赋值,因为之前 b 已经赋值过一次,因此这里会发生编译错误。
final 修饰基本类型变量和引用类型变量的区别
当使用 final 修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。 但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。

下面程序示范了 final 修饰数组和 Person 对象的情形。
import java.util.Arrays;
class Person {
private int age;
public Person() {
}
// 有参数的构造器
public Person(int age) {
this.age = age;
}
// 省略age的setter和getter方法
// age 的 setter 和 getter 方法
}
public class FinalReferenceTest {
public static void main(String[] args) {
// final修饰数组变量,iArr是一个引用变量
final int[] iArr = { 5, 6, 12, 9 };
System.out.println(Arrays.toString(iArr));
// 对数组元素进行排序,合法
Arrays.sort(iArr);
System.out.println(Arrays.toString(iArr));
// 对数组元素赋值,合法
iArr[2] = -8;
System.out.println(Arrays.toString(iArr));
// 下面语句对iArr重新赋值,非法
// iArr = null;
// final修饰Person变量,p是一个引用变量
final Person p = new Person(45);
// 改变Person对象的age实例变量,合法
p.setAge(23);
System.out.println(p.getAge());
// 下面语句对P重新赋值,非法
// p = null;
}
}
从上面程序中可以看出,使用 final 修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。例如上面 iArr 变量所引用的数组对象,final 修饰后的 iArr 变量不能被重新赋值,但 iArr 所引用数组的数组元素可以被改变。与此类似的是,p 变量也使用了 final 修饰,表明 p 变量不能被重新赋值,但 p 变量所引用 Person 对象的成员变量的值可以被改变。

注意:在使用 final 声明变量时,要求全部的字母大写,如 SEX,这点在开发中是非常重要的。

如果一个程序中的变量使用 public static final 声明,则此变量将称为全局变量,如下面的代码:
public static final String SEX= “女”;

final修饰方法
final 修饰的方法不可被重写,如果出于某些原因,不希望子类重写父类的某个方法,则可以使用 final 修饰该方法。

Java 提供的 Object 类里就有一个 final 方法 getClass(),因为 Java 不希望任何类重写这个方法,所以使用 final 把这个方法密封起来。但对于该类提供的 toString() 和 equals() 方法,都允许子类重写,因此没有使用 final 修饰它们。

下面程序试图重写 final 方法,将会引发编译错误。
public class FinalMethodTest {
public final void test() {
}
}
class Sub extends FinalMethodTest {
// 下面方法定义将出现编译错误,不能重写final方法
public void test() {
}
}
上面程序中父类是 FinalMethodTest,该类里定义的 test() 方法是一个 final 方法,如果其子类试图重写该方法,将会引发编译错误。

对于一个 private 方法,因为它仅在当前类中可见,其子类无法访问该方法,所以子类无法重写该方法——如果子类中定义一个与父类 private 方法有相同方法名、相同形参列表、相同返回值类型的方法,也不是方法重写,只是重新定义了一个新方法。因此,即使使用 final 修饰一个 private 访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名、相同形参列表、相同返回值类型的方法。

下面程序示范了如何在子类中“重写”父类的 private final 方法。
public class PrivateFinalMethodTest {
private final void test() {
}
}
class Sub extends PrivateFinalMethodTest {
// 下面的方法定义不会出现问题
public void test() {
}
}
上面程序没有任何问题,虽然子类和父类同样包含了同名的 void test() 方法,但子类并不是重写父类的方法,因此即使父类的 void test() 方法使用了 final 修饰,子类中依然可以定义 void test() 方法。

final 修饰的方法仅仅是不能被重写,并不是不能被重载,因此下面程序完全没有问题。
public class FinalOverload {
// final 修饰的方法只是不能被重写,完全可以被重载
public final void test(){}
public final void test(String arg){}
}
final修饰类
final 修饰的类不能被继承。当子类继承父类时,将可以访问到父类内部数据,并可通过重写父类方法来改变父类方法的实现细节,这可能导致一些不安全的因素。为了保证某个类不可被继承,则可以使用 final 修饰这个类。

下面代码示范了 final 修饰的类不可被继承。
final class SuperClass {
}
class SubClass extends SuperClass { //编译错误
}
因为 SuperClass 类是一个 final 类,而 SubClass 试图继承 SuperClass 类,这将会引起编译错误。
final 修饰符使用总结

  1. final 修饰类中的变量
    表示该变量一旦被初始化便不可改变,这里不可改变的意思对基本类型变量来说是其值不可变,而对对象引用类型变量来说其引用不可再变。其初始化可以在两个地方:一是其定义处,也就是说在 final 变量定义时直接给其赋值;二是在构造方法中。这两个地方只能选其一,要么在定义时给值,要么在构造方法中给值,不能同时既在定义时赋值,又在构造方法中赋予另外的值。
  2. final 修饰类中的方法
    说明这种方法提供的功能已经满足当前要求,不需要进行扩展,并且也不允许任何从此类继承的类来重写这种方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。在声明类中,一个 final 方法只被实现一次。
  3. final 修饰类
    表示该类是无法被任何其他类继承的,意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。

对于 final 类中的成员,可以定义其为 final,也可以不是 final。而对于方法,由于所属类为 final 的关系,自然也就成了 final 型。也可以明确地给 final 类中的方法加上一个 final,这显然没有意义。文章来源地址https://www.toymoban.com/news/detail-512773.html

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

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

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

相关文章

  • 问题:【IntelliJ IDEA】解决idea自动声明变量加finall修饰符问题

    1 new String() 2 快捷方式生成变量 final修饰的 settings-----》Editor------》Code Style--------》java下的这两个选项不被勾选 final modifier 然后在生成变量的时候,再次跳出来 dexlare final 的时候,按下 Alt+F 步骤三:如果上一步没有生效,重启idea file-invalidate caches

    2024年02月12日
    浏览(53)
  • 详解Jetpack Compose中的Modifier修饰符

            本文将会介绍Jetpack Compose中的Modifier。在谷歌官方文档中它的描述是这么一句话:Modifier元素是一个 有序、不可变 的集合,它可以往Jetpack Compose UI元素中添加修饰或者各种行为。例如,背景、填充和单击事件监听器装饰或添加行为到文本或按钮。         Mod

    2024年02月06日
    浏览(42)
  • java面试题(21):private修饰的方法可以通过反射访问,那么private的意义是什么?

    1 反射简介 Java,在一个类中,为了不让外界访问到某些属性和方法,通常将其设置为private,用正常的方式(对象名.属性名,对象名.方法名)将无法访问此属性与方法,但有没有其他方法可以访问呢?答案是有的,这就是java反射带来的便利。利用反射访问类的私有属性及方

    2024年01月22日
    浏览(41)
  • Java中的四种权限修饰符

    在Java中,存在四种访问修饰符,它们是public、private、protected和default。它们的访问权限从高到低依次为public protected default private。 1.public:public修饰的类、属性或方法可以被任何其他类访问,包括外部的类、同一个包内的类以及子类。 例如: 在这个例子中,Person类被声明为

    2024年02月12日
    浏览(57)
  • 浅析Java中的final关键字(详细)

    1.什么是final(概念) 2.final基本用法 3.深入理解final 4.final 的最佳实践 谈到final,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final 。final 是 Java 中的一个,可以用于修饰类、方法和变量。当一个类被声明为

    2024年02月03日
    浏览(66)
  • 【Spring进阶系列丨最终篇】一文详解Spring中的事务控制

    本篇文章是【Spring进阶系列】专栏的最后一篇文章,至此,我们对Spring的学习就告一段落,接下来我会持续更新【 Spring+SpringMVC+MyBatis整合 】专栏,欢迎免费订阅! 事务需要放在业务层(service) Spring的事务是基于AOP的 Spring的事务控制有两种:编程式事务【了解】和 声明式事务

    2024年04月25日
    浏览(34)
  • Java 中的访问修饰符有什么区别?

    Java 中的访问修饰符用于控制类、类的成员变量和方法的访问权限,主要有以下四种: public:公共访问修饰符,可以被任何类访问。public 修饰的类、成员变量和方法可以在任何地方被访问到。 protected:受保护的访问修饰符,可以被类本身、子类和同一个包中的其他类访问。

    2024年02月04日
    浏览(36)
  • 轻松理解Java中的public、private、static和final

    一、概念 1、public和private 两个都是访问权限修饰符,用于控制外界对类内部成员的访问。 public:表明对象成员是完全共有的,外界可以随意访问。用public修饰的数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用。 private:表明对象成员是完全私有的,不

    2024年02月16日
    浏览(44)
  • Bert-vits2-2.3-Final,Bert-vits2最终版一键整合包(复刻生化危机艾达王)

    近日,Bert-vits2发布了最新的版本2.3-final,意为最终版,修复了一些已知的bug,添加基于 WavLM 的 Discriminator(来源于 StyleTTS2),令人意外的是,因情感控制效果不佳,去除了 CLAP情感模型,换成了相对简单的 BERT 融合语义方式。 事实上,经过2.2版本的测试,CLAP情感模型的效果

    2024年02月04日
    浏览(47)
  • java中的异常,以及出现异常后的处理【try,catch,finally】

    异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。 注意: 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。 异常机制其实是帮助我们找到程序中的问题

    2024年02月08日
    浏览(42)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包