IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java随笔-final -> 正文阅读

[Java知识库]Java随笔-final

final

final可以用来修饰变量,方法和类。

final变量

若是被final修饰后,只能被赋值一次。

  • 声明成员变量后赋值
    在这里插入图片描述
    被final修饰后赋值一次后不能再进行修改,再次修改编译器会提示将final关键字去掉,否则编译不通过。

  • 声明成员变量后不赋值
    在这里插入图片描述
    声明后若是不赋值,则编译器编译不通过,提示必须在构造方法中进行初始化,而且在后续的操作中不能再对它进行修改。

  • 引用类型
    在这里插入图片描述
    引用类型被final修饰后,即使初始值设置为null,也算一次赋值,后续无法再为该引用创建对象。虽然对象引用不能再修改,但是对象的属性可以被修改。

    // 引用类型
    private final Person person = null;
    
    private void test() {
        person.setName("final");
    }

上诉代码肯定无法运行,因为person为null,会出现 NullPointerException。

    // 引用类型
    private static final Person person = new Person();
    
    public static void main(String[] args) {
        System.out.println(person.getName());
        person.setName("name1");
        System.out.println(person.getName());
        person.setName("name2");
        System.out.println(person.getName());
    }

结果:

null
name1
name2

开始创建对象没有赋值,所以输出null,当赋值为name1时输出name1,修改为name2后输出为name2,说明被final修饰的对象的属性是可以被修改的。

  • 数组
    // final数组
    private static final int[] values = {1,2,3,4,4};

    public static void main(String[] args) {
        // 报错
//        values = {9,8,7,6,5};
        values[0] = 10;
        for (int value : values) {
            System.out.print(value + ",");
        }
    }

结果:

10,2,3,4,4,

说明final修饰的数组同样不能修改,但是数组里面的元素是可以修改的,该属性常用于内部类中。

  • 匿名内部类
    public static void main(String[] args) {
        final int testValue = 1;
        // 匿名内部类
        new Thread(() -> {
            System.out.println(testValue);
        });
    }

若在匿名内部类中使用局部变量,该变量需要声明为final,若是想要进行修改,还是需要将变量改成final数组。

    public static void main(String[] args) {
        final int[] testValue = {1};
        // 匿名内部类
        new Thread(() -> testValue[0]++);
    }
被final修饰后
  • 若是基本数据类型,此时变量会变成常量,不能再进行修改;
  • 若是成员变量则需要在声明后马上赋值,或在构造方法中赋值,否则编译报错;
  • 若是引用数据类型,则对象或数组的引用无法修改,但对象或数组里面的元素可以修改;
  • 匿名内部类中使用所有局部变量都需要声明为final。

final方法

父类:

public  class Parent {

    // final方法
    public final void family(){}
}

子类:
在这里插入图片描述

  • final方法不能被重写。

final类

父类:

public final class Parent {
    
    public void family(){}
}

子类:
在这里插入图片描述

  • 当类被声明为final类,该类就无法进行扩展,也就是无法被继承。
  • 若一个类被声明为final类,该类中所有的方法都会自动变成final方法,无法被重写。类不能被继承,里面的方法自然无法被重写。
  • final与abstract互斥,final是禁止扩展的,而abstract是必须扩展的,否则没有意义,所以两者不能同时使用。

修改final变量值

被final修饰的变量只能被赋值一次,若是需要修改可以利用反射进行修改。

    // 需要修改的数据
    private final int value = 1;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        // 反射修改final变量
        FinalTest test = new FinalTest();
        // 找到需要被修改的变量
        Field field = FinalTest.class.getDeclaredField("value");
        // 突破访问权限
        field.setAccessible(true);
        // 将value = 1,修改为value =2
        field.set(test,2);
        // 输出修改后的值
        System.out.println(test.value);
    }

结果:

1

输出结果为1,不能说明修改不成功,而是编译器对于基本数据类型进行的内联优化,也就是代码中的value直接被1取代了,不需要再通过value去查1。查看编译后的class文件可知。

/ .class 文件 //
    private final int value = 1;
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        FinalTest test = new FinalTest();
        Field field = FinalTest.class.getDeclaredField("value");
        field.setAccessible(true);
        field.set(test, 2);
        PrintStream var10000 = System.out;
        Objects.requireNonNull(test);
        var10000.println(1);
    }

编译后的.class文件中value直接被1取代了,所以输出语句 System.out.println(test.value)被直接编译成了 var10000.println(1),所以输出结果为1。
若是想查看被修改后的值,输出语句需要改成System.out.println(field.get(test))。

    // 需要修改的数据
    private final int value = 1;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        // 反射修改final变量
        FinalTest test = new FinalTest();
        // 找到需要被修改的变量
        Field field = FinalTest.class.getDeclaredField("value");
        // 突破访问权限
        field.setAccessible(true);
        // 将value = 1,修改为value =2
        field.set(test,2);
        // 输出修改后的值,相当于动态获取
        System.out.println(field.get(test));
    }

结果:

2
  • 编译器的此次优化只针对基本数据类型,引用数据类型修改后会马上生效。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:22:29  更:2022-03-04 15:23:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:31:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码