Java的final修饰符

news/2024/11/8 23:11:12/

final 实例域

可以将实例域定义为 final。对于 final 域来说,构建对象时必须初始化 final 实例域,构造对象之后就不允许改变 final 实例域的值了。也就是说,必须确保在每一个构造器执行之后,final 实例域的值被设置,并且在后面的操作中,不能够再对 final 实例域进行修改。

例如,可以将 Employee 类中的 name 域声明为 final,因为在对象构建之后,这个值不会再被修改,即没有 setName() 方法。

class Employee {private final String name;...
}

final 修饰符大都应用于基本(primitive)类型域,或不可变(immutable)类的域(如果类中的每个方法都不会改变其对象,这种类就是不可变的类。例如,String 类就是一个不可变的类)。

对于可变的类,使用 final 修饰符可能会对读者造成混乱。例如,private final StringBuilder evaluations; 在 Employee 构造器中会初始化为 evaluations = new StringBuilder(); final 关键字只是表示 evaluations 对象变量不会再指向其他的 StringBuilder 对象。不过这个 StringBuilder 对象可以更改。

public void giveGoldStar() {evaluations.append(LocalDate.now() + ": Gold star!\n");
}

final 类和方法

阻止继承:final 类和方法。

有时候,可能希望阻止人们利用某个类定义子类。不允许扩展的类被称为 final 类。如果在定义类的时候使用了 final 修饰符就表明这个类是 final 类。如果将一个类声明为 final,其中的所有方法自动地成为 final,而不包括数据域(final 类的数据域不会自动地成为 final 域)。

例如,假设希望阻止人们定义 Executive 类的子类,就可以在定义 Executive 这个类的时候,使用 final 修饰符声明。声明格式如下所示:

public final class Executive extends Manager {}

类中的特定方法也可以被声明为 final。如果这样做,子类就不能覆盖这个方法例如:

public class Employee {public final String getName() {return name;} 
}

将方法或类声明为 final 主要目的是:确保它们不会在子类中改变语义。例如:

  • Calendar 类中的 getTime() 和 setTime() 方法都声明为 final。这表明 Calendar 类的设计者负责实现 Date 类与日历状态之间的转换,而不允许子类处理这些问题。
  • 同样地,String 类也是 final 类,这意味着不允许任何人定义 String 的子类。换言之,如果有一个 String 的引用,它引用的一定是一个 String 对象,而不可能是其他类的对象。

有些程序员认为:除非有足够的理由使用多态性,应该将所有的方法都声明为 final。事实上,在 C++ 和 C# 中,如果没有特别地说明,所有的方法都不具有多态性。这两种做法可能都有些偏激。我们提倡在设计类层次时,仔细地思考应该将哪些方法和类声明为 final。

参考资料

《Java核心技术卷一:基础知识》(第10版)第 4 章:对象与类 4.3.9 final 实例域

《Java核心技术卷一:基础知识》(第10版)第 5 章:继承 5.1.7 阻止继承:final 类和方法


http://www.ppmy.cn/news/53049.html

相关文章

C++时间和时间戳的转换

文章目录 时间戳转标准时间标准时间转时间戳方法一&#xff1a;方法二方法三 &#xff08; 微秒 &#xff09; 时间戳转标准时间 // timestamp.cpp#include <stdio.h> #include <time.h> #include <iostream> #include <string>using namespace std;t…

Go语法和特性

文章目录 1、语法基础1.1 环境安装1.1.1 安装1.1.2 编译工具 1.2 基本语法1.2.1 变量的声明与初始化1.2.1 原生数据类型1.2.2 指针1.2.3 常量与类型别名1.2.4 分支与循环 1.3 容器1.3.1 数组1.3.2 列表1.3.2 字典1.3.3 容器遍历 1.4 函数与接口1.4.1 函数声明和参数传递1.4.2 匿…

RocketMq windows 安装

RocketMq安装步骤&#xff1a; 1、直接在官网下载。也可以从这里自取 https://rocketmq.apache.org/download/ 2、修改bin目录下的文件 runserver.cmd 和 runbroker.cmd文件。主要修改所占用内存的大小。 runserver.cmd 修改如下&#xff1a; runbroker.cmd 修改如下&#xff…

学生信息管理系统简易版(文件读写操作)

功能模块 具体功能如下&#xff1a; 添加学生信息修改学生信息&#xff08;按学号&#xff09;排序&#xff08;分别按总分升序、降序、以及按姓名升序&#xff09;查找学生&#xff08;按学号&#xff09;删除学生查看所有学生信息 数据结构体设计 本表设计一个学生信息的结…

Springcloud连接nacos集群,nacos地址配置为nginx,报错:requst nacos server failed

先说下版本&#xff1a; Spring cloud&#xff1a; Hoxton.SR12 spring.cloud.alibaba&#xff1a; 2.2.9.RELEASE spring.boot&#xff1a; 2.3.12.RELEASE Linux Centos7 nacos-server&#xff1a;2.1.0 nginx&#xff1a; 1.20.2 环境说明&#xff1a; nacos正常搭建三个集…

windows 环境下,可执行 exe 文件和 .dll 文件在不同目录下的处理办法

在 Windows 操作系统中&#xff0c;当可执行 exe 文件需要使用某个.dll 文件时&#xff0c;它会在以下几个地方寻找该文件&#xff1a; 首先&#xff0c;它会在与可执行文件相同的目录中查找该文件。 如果找不到该文件&#xff0c;则会在系统搜索路径中查找该文件。 因此&…

CentOS stream9下安装kubernetes1.19

配置docker的yum仓库 wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo 安装containerd yum install containerd 目前kubernetes不基于docker&#xff0c;而是基于 containerd.io &#xff0c;所以不需要安装do…

用户界面对象的线程亲缘性第一篇: 窗口

不同的对象具有不同的线程亲缘性规则&#xff0c;但其基本原则来自古老的 16 位 Windows。 在 Windows 系统上&#xff0c;最重要的用户界面对象当然是窗口了。窗口对象有它自己的线程亲缘性。创建窗口的线程是与窗口具有不可分割关系的线程。非正式地说&#xff0c;线程”拥有…