首页 > 编程语言 >【Java21】final修饰符

【Java21】final修饰符

时间:2024-07-17 15:26:11浏览次数:8  
标签:Java21 变量 初始化 void 修饰符 final 修饰 public

final可以用来修饰类、变量和方法。类似C++里的const,表示被修饰的类、变量和方法不可改变。具体表现为:

  • 对变量,一旦初始化之后就不可改变。final即可修饰成员变量(类变量|实例变量),也可修饰局部变量、形参。

final修饰的变量并不是不能赋值,而是不能被重新赋值。一旦获得初始值之后,就不能修改的意思。

final修饰成员变量

成员变量本身是随着类初始化或者对象初始化而初始化的。

成员变量在何种情况下会被初始化?

  • 类初始化时,系统为类变量分配内存空间并分配默认值;

    • 类初始化块代码中可以对类变量赋初始值;
  • 创建对象时,系统为实例变量分配内存空间并分配默认值;

    • 实例初始化块、构造器中可以对实例变量赋初始值。

如果不显示给final修饰的变量赋初始值,那么它将始终是默认值。那这个变量就失去了声明的意义了。因此,Java约定,final成员变量必须显式指定初始值

根据上面的情形,重新总结一下:

  1. final修饰的类变量,必须在类初始化块中赋初值,或者在声明该类变量时赋值。二者只能选其一(因为不能重复赋值)。
  2. final修饰的实例变量,必须在实例初始化块、构造器中赋初值,或者在声明的时候赋值。三者只能选其一。

注意,一定要对final修饰的成员变量显式赋初始值,而且不要在初始化之前访问它。

Java不允许在final变量初始化前直接访问它;但是,Java又允许通过方法,在初始化之前访问final修饰的成员变量。此时不会报错,但是只会输出默认值。这显然违背了final的使用初衷:让程序始终访问到固定的值的变量。

因此,我们在编程时不要在final显式初始化之前访问它。

final局部变量

局部变量必须由程序员显式初始化。因此,有两个位置可以对final修饰的局部变量赋值,一个是在定义时;一个是第一次正常赋值。

形参在调用该方法时,由外部传入的参数在初始化。因此在方法内不能对final修饰的形参赋值。

public void test(final int a)
{
  a = 5; // 非法
}
final修饰基本类型和引用类型

final修饰基本类型,就是值,一旦赋初值之后就无法改变,这很好理解。

但是,final修饰引用类型时,因为引用类型实际上是指针,final只能确保它指向的对象不变,即永远引用同一个对象。但是对象本身是可以改变的。

class Person
{
    private int age;
    public Person(){}
    public Person(int age)
    {
        this.age = age;
    }
    // 省略set和get方法
}

public class Test
{
    public static void main(String[] args)
    {
        // 使用final修饰数组,数组是引用变量
        final int[] iArr = {5,6,12,9};
        // 对数组排序,合法
        Arrays.sort(iArr);
        // 对数组元素赋值,合法
        iArr[2] = -8;
        // 但是更改iArr的值,非法
        // iArr = null;
        // ------
        // 使用final修饰对象,对象也是引用变量
        final var p = new Person();
        // 修改p指向对象的age的值,合法
        p.setAge(10);
        // 试图修改p的指向,非法
        //p = null;
    }
}
final与宏替换

若final变量,不管是类变量、实例变量还是局部变量,只要:

  • 使用final修饰;
  • 定义final的同时指定了初值;
  • 该初值在编译时就可以确定下来;

那么这个变量其实就是一个“宏变量”,编译器在编译时会直接把该变量替换成那个值。

变量不存在了!

public class FinalLocalTest
{
  public static void main(String[] args)
  {
    final var a = 5; // 满足上述3条特征
    System.out.println(a);
  }
}

第6行,编译后实际上就是System.out.println(5);

注意,上面第3条,只要在编译时能确定初值就行。也就是说,赋值运算符右边(右值)可以是表达式、字符串连接等。只要不包含访问其他变量、调用方法就可以:

public class FinalReplaceTest()
{
  public static void main(String[] args)
  {
    final var a = 5 + 2; // OK
    final var b = 1.2 / 3; // OK
    final var str = "疯狂" + "Java"; // OK
    final var book = "疯狂" + 99.0; // 字符串连接,OK
    final var book 2 = "疯狂" + String.valueOf(99.0); // 调用了方法,不OK
  }
}

为什么调用方法或者访问其他变量不行?因为Java的特点是所有方法和变量都是类成员。那么在调用时,一定要经过实例化才行。实例化分配堆内存,在编译时是不能确定的。

final方法

final修饰的方法不可被重写。当不希望子类重写父类的某个方法时,可以用final修饰。

public class FinalMethodTest
{
	public final void test(){}
}

class Sub extends FinalMethodTest
{
  public void test(){} // 不OK,试图重写父类的final方法
}

但请注意,这里也有一个“bug”,或者说final失灵的情况:当父类的方法是private时,由于子类本身就看不见,无法访问,所以不涉及到重写。如果子类定义了一个一模一样的方法,也不算重写,而是定义了一个新方法。在这种情况下,即使父类方法使用final修饰,也没用。

public class PrivateFinalMethodTest
{
  private final void test(){};
}

class Sub extends PrivateFinalMethodTest
{
  public void test(){} // OK
}

另外,要注意final只能阻止重写,不能阻止重载!

public class FinalOverload
{
  public final void test(){}
  public final void test(String arg){} // 完全OK
}
final

final修饰的类不能有子类。

小结

final可以修饰变量、方法和类,其效果分别是:

  • 修饰变量,该变量只能被赋一次初始值;
  • 修饰方法,该方法不能被子类重写;
  • 修饰类,该类不能被继承。

标签:Java21,变量,初始化,void,修饰符,final,修饰,public
From: https://blog.csdn.net/wangxiaochaun/article/details/140496406

相关文章

  • Java基础,final关键字,权限修饰符,内部类,抽象类和接口作为方法的参数和返回值,System类,Obj
    一.final关键字1.final:不可以改变,可以用来修饰类,方法和变量类:被修饰的类,不能被继承方法:被修饰的方法,不能被重写变量:被修饰的变量,不能被重新赋值2.格式:    修饰类:finalclass类名{}    修饰方法:publicfinal返回值类型方法名(){}    修饰变量:fin......
  • [Java]面试官:你对异常处理了解多少,例如,finally中可以有return吗?
    【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)https://www.cnblogs.com/cnb-yuchen/p/18299911出自【进步*于辰的博客】参考笔记一,P35.4/5。目录1、介绍2、try...with...resources最后1、介绍相信大家对try...catch...finally都很熟悉了,在此我提一点使用细......
  • Java基础之——final关键字的使用
    #Java基础复习##参考文章:Java:final关键字的作用(方法、变量、类)_java语言中在类定义时使用final关键字修饰是指这个类-CSDN博客#一、理解含义final是Java中一个保留的关键字,可以用于修饰变量、方法和类。任何实体(变量,方法或类)一旦被声明final后,只能分配(赋值)一次。也就是......
  • 如何在 SwiftUI 中熟练使用 visualEffect 修饰符
    文章目录前言介绍visualEffect什么是视觉效果?visualEffect修饰符视觉效果完整的代码总结前言在WWDC23中,SwiftUI引入了一个名为visualEffect的新视图修饰符。此修饰符允许我们通过访问特定视图的布局信息来附加一组可动画化的视觉效果。下面我们将学习如何......
  • Java中的final关键字详解
    Java中的final关键字详解大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!1.final关键字的基本用法在Java中,final关键字可以用来修饰类、方法和变量,具有不同的含义和作用。下面我们逐一介绍其在各个方面的应用。2.final修饰类当一个类被final修饰时,表......
  • Java 修饰符
    Java中的修饰符用于修饰类、方法、变量等元素,它们控制了这些元素的访问性、继承性和其他特性。主要的修饰符包括:1.**访问控制修饰符**:  -**public**:可以被任何其他类访问。  -**protected**:可以被同一包内的类及其子类访问。  -**default(nomodifier)*......
  • C#中的异常捕获 try catch finally
    处理异常提供的四个关键字,try...catch...finally...throwfinally最后,不管异常是否被抛出都会执行,例如打开一个文件,不管是否出现异常都需要关闭,throw:当问题出现的时候程序可以抛出一个异常,使用throw关键字抛出异常,try{执行的代码}catch(ExceptionNamee1){处理异常t......
  • E. Final Countdown
    原题链接题解由于数位很大,所以要朝着数位方向想,对于从左到右数第\(i\)位,其贡献为\([1,i-1]\)位组成的数字*10+\(s_i\),等于\([1,i]\)区间放到了答案的\([n-i+1,n]\)code#include<bits/stdc++.h>usingnamespacestd;inta[400005]={0};intmain(){intt;......
  • 【JAVA】权限修饰符
    一,认识权限修饰符(public,protected,“空”,private)public(公共的)1.public对所有类可见。使用对象:类、接口、变量、方法·被声明为public的类、方法、构造方法和接口能够被任何其他类访问。·如果这些类分布在不同的包中,那么我们可以通过导包(import关键字)进行导包就能操作......
  • [SWPUCTF 2021 新生赛]finalrc
    [SWPUCTF2021新生赛]finalrc<?phphighlight_file(__FILE__);if(isset($_GET['url'])){$url=$_GET['url'];if(preg_match('/bash|nc|wget|ping|ls|cat|more|less|phpinfo|base64|echo|php|python|mv|cp|la|\-|\*|\"|\>|......