当前位置: 首页 > article >正文

final-关键字

一、final修饰的类不能被继承

当final修饰一个类时,表明这个类不能被其他类继承。例如,在 Java 中,String类就是被final修饰的,这保证了String类的不可变性和安全性,防止其他类通过继承来改变String类的行为。

final class MyFinalClass {
    // 类的成员和方法
}

// 以下代码会报错,因为不能继承final类
class Subclass extends MyFinalClass {
}

二、final修饰的方法不能被覆盖(重写)

用final修饰的方法不能在子类中被覆盖(重写)。这可以防止子类意外地改变父类中关键方法的行为,保证了方法的功能和语义在继承体系中的稳定性。

class Parent {
    public final void finalMethod() {
        System.out.println("这是父类的final方法");
    }
}

class Child extends Parent {
    // 以下代码会报错,不能覆盖final方法
    @Override
    public void finalMethod() {
        System.out.println("尝试覆盖父类的final方法");
    }
}

三、final修饰的变量,一旦赋值不能重新赋值

  • 基本数据类型final修饰的基本数据类型变量,一旦赋值就不能再重新赋值。例如:
    final int num = 10;
    num = 20; // 这行代码会报错,不能重新赋值给final变量

final int k;
        // 首次初始化时可以的。
        k = 200;
        // 再次重新赋值是不允许的,因为final的。
        //k = 300;
  • 引用数据类型
    • final修饰的引用变量,一旦指向某个对象后,就不能再指向其他对象,但指向的对象内部的数据是可以修改的。例如:

示例1:

final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 合法,修改对象内部的数据
sb = new StringBuilder("New"); // 这行代码会报错,不能重新赋值给final引用变量

示例2:

Product类:

public class Product {
    private String name;
    private double price;

    public Product() {
    }

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public void display(){
        System.out.println("商品名称:" + this.name + ",商品价格:" + this.price);
    }
}

ProductTest类:

public class ProductTest {
    public static void main(String[] args) {
        // 创建商品对象
        final Product pro = new Product("BMW535li", 10.0);

        pro.display();

        // 报错
        //pro = new Product("BenzE300L", 20.0);

        // 指向的对象的内部内存可以修改。没问题。
        pro.setName("BenzE300L");
        pro.setPrice(20.0);

        pro.display();

    }
}

运行结果:

四、final修饰的实例变量必须在对象初始化时手动赋值

final修饰的实例变量确实必须在对象初始化时手动赋值,这是 Java 语言的规定,主要有以下几种实现方式及相关要点:

1.在定义时直接赋值

可以在声明final实例变量的同时直接为其赋初始值,这是一种较为常见和直观的方式。

class MyClass {
    // 在定义时直接给final实例变量赋值
    final int instanceVar = 10; 

    // 其他方法和成员
}

2.在构造函数中赋值

final修饰的实例变量。必须在构造方法执行完之前手动赋上值。(不允许采用系统默认值) 一般不存在这种情况。

示例1:

class MyClass {
    final int instanceVar; 

    public MyClass() {
        // 在构造函数中给final实例变量赋值
        instanceVar = 10; 
    }

    // 其他方法和成员
}

示例2:

public class User {
    final String name;
    final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  • 如果一个类有多个构造函数,那么每个构造函数都必须为final实例变量赋值,以保证无论通过哪个构造函数创建对象,final实例变量都能得到正确的初始化。
class MyClass {
    final int instanceVar; 

    public MyClass() {
        instanceVar = 10; 
    }

    public MyClass(int value) {
        // 在另一个构造函数中也给final实例变量赋值
        instanceVar = value; 
    }

    // 其他方法和成员
}

3.在实例初始化块中赋值

还可以使用实例初始化块来为final实例变量赋值,实例初始化块会在构造函数执行之前执行,也能确保final实例变量在对象初始化时被赋值。

class MyClass {
    final int instanceVar; 

    {
        // 在实例初始化块中给final实例变量赋值
        instanceVar = 10; 
    }

    // 其他方法和成员
}

如果final修饰的实例变量没有在上述这些时机进行手动赋值,编译器就会报错,提示变量未初始化。这一规则保证了final实例变量在使用前总是有一个确定的值,体现了final关键字所代表的 “不可变” 语义,有助于提高程序的稳定性和可维护性,避免出现因变量未初始化或意外修改而导致的错误。

五、final修饰的实例变量一般和static联合使用:称为常量

当final修饰的实例变量和static联合使用时就形成了常量,以下是关于它的详细介绍:

定义与特点

用final和static修饰的变量被称为类常量,它属于类本身,而不是类的某个具体实例。在内存中,类常量只有一份存储,被所有该类的实例共享。并且由于final的作用,一旦被赋值,其值在程序运行期间就不能再被修改。

命名规范

按照 Java 的命名规范,常量通常使用大写字母命名,多个单词之间用下划线分隔,这样可以清楚地表明它是一个常量,与其他变量区分开来。例如:

public class MathConstants {
    public static final double PI = 3.141592653589793;
    public static final int MAX_VALUE = 100;
}

应用场景

数学和物理常量:在科学计算或数学相关的程序中,经常会用到一些固定的数学或物理常量,如圆周率PI、重力加速度G等,将它们定义为常量可以方便在代码中使用。

配置参数:在应用程序中,可能会有一些配置参数,如数据库连接字符串、系统默认设置等,将这些参数定义为常量可以在整个应用程序中统一使用,并且方便修改和维护。

状态码和枚举值:在网络通信或系统交互中,常常会用到一些固定的状态码或枚举值来表示不同的状态或类型,将它们定义为常量可以使代码更加清晰和易于管理。例如

public class HttpStatusCodes {
    public static final int OK = 200;
    public static final int BAD_REQUEST = 400;
    public static final int INTERNAL_SERVER_ERROR = 500;
}


http://www.kler.cn/a/529645.html

相关文章:

  • 机器学习优化算法:从梯度下降到Adam及其变种
  • PHP 常用函数2025.02
  • Unity实现按键设置功能代码
  • 创建前端项目的方法
  • 单细胞分析基础-第一节 数据质控、降维聚类
  • OVS-DPDK
  • 穷举vs暴搜vs深搜vs回溯vs剪枝系列一>单词搜索
  • wax到底是什么意思
  • 【高级篇 / IPv6】(7.6) ❀ 03. 宽带IPv6 - ADSL拨号宽带上网配置 ❀ FortiGate 防火墙
  • 53. Uboot命令使用
  • 通过 Docker 部署 Mastodon 服务器 的教程
  • Vue.js 使用 `teleport` 实现全局挂载
  • 低成本、高附加值,具有较强的可扩展性和流通便利性的行业
  • 数据建模中的Chasm 陷阱
  • 更高效地使用Adobe软件,提升创作质量
  • Perl语言的函数实现
  • Echarts 封装通用组件
  • mysql大表的解决方案,及Hive分页查询
  • 康德哲学与自组织思想的渊源:从《判断力批判》到系统论的桥梁
  • 注解(Annotation)
  • 【深度学习】softmax回归的简洁实现
  • JPA中基本类型集合的映射与操作实例
  • [SAP ABAP] SE11 / SE16N 修改标准表(慎用)
  • java练习(5)
  • GMSL 明星产品之 MAX96724
  • CNN的各种知识点(四): 非极大值抑制(Non-Maximum Suppression, NMS)