47从零开始学Java之详解final修饰符、常量、常量方法与常量类

news2024/9/28 1:24:46

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

壹哥之前跟大家说过,在面向对象中,有abstract、static和final 这3个核心修饰符。截止到现在,我们已经把abstract与static修饰符学习完毕,接下来就让我们再来学习final修饰符的用法与特性吧。

-----------------------------------------------前戏已做完,精彩即开始---------------------------------------------

全文大约【3500】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github:

GitHub - SunLtd/LearnJava

Gitee:

一一哥/从零开始学Java

一. final修饰符

1. 简介

在Java中,final表示“最终的、不可改变的、完结的”,它也是一种修饰符,可以修饰变量、方法和类final修饰变量、方法和类时的意义是不同的,但本质是一样的,都表示不可改变,类似C#里的sealed关键字。final修饰的变量叫做最终变量,也就是常量,修饰的方法叫做最终方法,修饰的类叫做最终类

2. 配套视频

与本节内容配套的视频链接如下:

Bilibili External Player

二. 常量

1. 概念

被final修饰的变量一旦被赋值初始化后,就不能再被重新赋值。即变量值只能被赋值一次,不可被反复修改,所以叫做最终变量,也叫做常量

并且我们在定义final变量时,必须显式地进行初始化,指定初始值,否则会出现“The blank final field xxx may not have been initialized”的异常提示。变量值的初始化,可以在两个地方:一是在变量定义处,即在final变量定义时直接给其赋值;二是在构造方法或静态代码块中。这些地方只能选其一,不能同时既在定义时赋值,又在构造方法或静态代码块中另外赋值。

我们在开发时,通常会把final修饰符和static修饰符一起使用,来创建类的常量。

2. 特性

根据修饰变量的作用范围,比如在修饰局部变量和成员变量时,final会有不同的特性:

  • final修饰局部变量时在使用之前必须被赋值一次才能使用;
  • final修饰成员变量时,如果在声明时没有赋值,则叫做“空白final变量”,空白final变量必须在构造方法或静态代码块中进行初始化。

根据修饰变量的数据类型,比如在修饰基本类型和引用类型的变量时,final也有不同的特性:

  • final修饰基本类型的变量时不能把基本类型的值重新赋值,因此基本类型的变量值不能被改变。
  • final修饰引用类型的变量时,final只会保证引用类型的变量所引用的地址不会改变,即保证该变量会一直引用同一个对象。因为引用类型的变量保存的仅仅是一个引用地址,所以final修饰引用类型的变量时,该变量会一直引用同一个对象,但这个对象本身的成员和数据是完全可以发生改变的。

3. 语法

final修饰变量时,常用的语法格式如下:

final String 变量名=变量值;

我们在使用final声明变量时,一般会要求变量名的单词全部大写,且变量名由多个单词组成时,多个单词之间用下划线“_”分隔开,比如“SCHOOL_NAME”。

4. 案例

4.1 修饰局部变量

以下案例是final修饰局部变量时的用法和特性。

/**
 * @author 一一哥Sun 
 */
public class FinalDemo {
	// final修饰局部变量,该变量使用之前要赋初值
	public void declareFinal() {
		// 先声明变量
		final int x;
		// 再赋初值,该值只能赋一次,否则会报错。
		x = 200;
		//The final local variable x may already have been assigned
		//x = 400;
		System.out.println("x=" + x);

		// 声明的同时赋值
		final int y = 300;
		System.out.println("y=" + y);
	}
}

从上述案例中可知,局部常量最好是在声明时就进行初始化。而且常量只能被赋值一次,否则会出现编译错误:“The final local variable xxx may already have been assigned”。

4.2 修饰成员变量

以下案例是final修饰成员变量时的用法和特性。

/**
 * @author 一一哥Sun 
 */
public class FinalDemo {
	//final修饰成员变量
	// 实例常量
	final int a = 10; // 直接赋值
	final int b; // 空白final变量,需要在构造方法中进行初始化
	// 静态常量
	final static int c = 20;// 直接赋值
	final static int d; // 空白final变量,需要在静态代码块中进行初始化

	static {
		// 初始化静态变量
		d = 40;
	}

	FinalDemo() {
		// 初始化成员变量
		b = 20;
		// 不能第二次赋值,否则会发生编译错误
		// The final local variable b may already have been assigned
		//b = 30;
	}
}

从上述代码中可知,空白final变量,可以在构造方法或静态代码块中初始化。

4.3 修饰基本类型的变量

以下案例是final修饰基本类型变量时的用法和特性。final修饰基本类型的变量时,不能把基本类型的变量重新赋值,因此基本类型的变量值不能被改变,否则会出现“The final local variable x cannot be assigned. It must be blank and not using a compound assignment”的异常。

/**
 * @author 一一哥Sun 
 */
public class FinalTypeDemo {
	public static void main(String[] args) {
		//final修饰基本类型的变量,变量值不可变
		final int x=10;
		//The final local variable x cannot be assigned. It must be blank and not using a compound assignment
		//x=20;
		System.out.println("x="+x);
	}
}

4.4 修饰引用类型的变量

以下案例是final修饰引用类型变量时的用法和特性。final修饰引用类型的变量时,final只会保证引用类型的变量所引用的地址不会改变,即保证该变量会一直引用同一个对象,否则会出现“Array constants can only be used in initializers”或者“The final local variable user cannot be assigned. It must be blank and not using a compound assignment”的异常。

import java.util.Arrays;

/**
 * @author 一一哥Sun 
 */
public class FinalTypeDemo {
	public static void main(String[] args) {
		// final修饰数组变量,nums是一个引用变量
        final int[] nums = { 1, 9, 7, 3 };
        System.out.println(Arrays.toString(nums));
        
        //final修饰引用类型时,引用的地址不可变,但引用对象本身的数据内容是可变的
        //Array constants can only be used in initializers
        //nums= {2,0,8,1};
        // 对数组里的元素赋值修改没问题
        nums[2] = 10;
        System.out.println(Arrays.toString(nums));
        
        // final修饰Person变量,p是一个引用变量
        final User user = new User();
        // 改变Person对象的age实例变量,合法
        user.setAge(18);
        System.out.println(user.getAge());
        
        //对user变量的引用地址重新赋值,非法
        //The final local variable user cannot be assigned. It must be blank and not using a compound assignment
        //user = new User(30);
	}
}

从上面的两个案例中,我们可以得知,使用 final修饰引用类型的变量时,变量不能被重新赋值,但我们可以改变该变量所引用对象里的内容。

三. 常量方法

1. 概念

被final修饰的方法称为常量方法,该方法可以被重载,也可以被子类继承,但却不能被重写。当一个方法的功能已经可以满足当前要求,不需要进行扩展,我们就不用任何子类来重写该方法,防止该方法的内容被修改。比如Object类中,就有一个final修饰的getClass()方法,Object的任何子类都不能重写这个方法。

2. 语法

final修饰方法时,常用的语法格式如下:

修饰符 final 返回值类型 方法名(){
    //方法体
}

3. 案例

3.1 子类不能重写父类的final方法

如果我们在父类中定义一个final方法,子类继承父类后,子类不能重写父类中的这个final方法,否则会出现“Cannot override the final method from Father”异常。但是我们要注意,final方法是可以被重载的!

/**
 * @author 一一哥Sun 
 */
public class Father {
	private String name;
	
	public final void setName(String name) {
		this.name=name;
	}

    //重载final方法
	public final void setName(String firstName,String lastName) {
		this.name=firstName+lastName;
	}

}

//子类继承父类
public class Son extends Father{
	private String name;
	
	//子类不能重写父类中的final方法!
	//Cannot override the final method from Father
	//public void setName(String name) {
	//	this.name=name;
	//}
}

3.2 父类中私有的final方法

如果我们在父类中定义了一个私有的private方法,因为它只能在当前类中可见,其子类无法访问该方法,所以子类也就无法重写该方法。如果子类中也定义了一个与父类中完全相同的private方法,这也不算方法重写,这只是重新定义了一个新方法。因此,即使我们使用final修饰private方法,我们也可以在其子类中定义与该方法相同的方法。

/**
 * @author 一一哥Sun 
 */
public class Father {
	private double salary;
	//父类中私有的方法
	private final void setSalary(double salary) {
		this.salary=salary;
	}
}

//子类继承父类
public class Son extends Father{
	private double salary;
	//子类中定义与父类同名通参的方法,这不属于方法重写!
	private void setSalary(double salary) {
		this.salary=salary;
	}
}

4. 配套视频

与本节内容配套的视频链接如下:

Bilibili External Player

四. 常量类

1. 概念

我们知道,通常子类继承父类时,子类可以访问父类的内部数据,并可通过重写父类的方法来改变父类方法的实现细节。但这样做可能会导致一些不安全的因素,所以为了保证某个类不可被继承,我们就可以使用final来修饰这个类。被final修饰的类称为常量类,这种类不能被继承,也就不能被修改或扩展

final类无法被任何其他类继承,这意味着该类在Java的继承树体系中是一个叶子类,比如我们经常使用的String类,就是典型的final类。如下图所示:

final类中的成员,我们可以用final修饰,也可以不用final修饰。比如final类中的方法,因为这些方法本身就属于final类,该类都不能被子类继承,里面的所有方法自然也就不能被子类重写,那么这些方法自然也就成了final型。所以final中的变量和方法,我们都没必要再单独添加final修饰符了。

2. 语法

final修饰类时,常用的语法格式如下:

访问修饰符 final class 类名{
    //....
}

3. 实现案例

/**
 * @author 一一哥Sun 
 * 父类是final类
 */
public final class Father {
	......
}

//此时子类不能继承父类,否则会出错!
public class Son extends Father{
	......
}

从上面的代码中我们可以验证得知,final类不能被继承,final类中的方法更不可能被重写,否则会出现“The type Son cannot subclass the final class Father”异常,如下图所示:

4. 配套视频

与本节内容配套的视频链接如下:

Bilibili External Player

-------------------------------------------------​​​​​​​正片已结束,来根事后烟-----------------------------------------------

五. 结语

至此,壹哥就把final与常量、常量方法、常量类等相关内容讲解完毕了,现在你知道final的特性都有哪些吗?最后壹哥给大家总结如下:

  • final修饰的变量,其变量值不可被改变,此时的变量被称为常量;
  • final修饰引用类型的变量时,引用地址不可变,但对象中的数据可变;
  • final修饰的方法不可以被重写;
  • final修饰的类不可以被继承,即不能有子类。

另外如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

六. 今日作业

class MyClass{
    final int value; 
    public MyClass(){
    }
    
    public MyClass(int value){
        this.value=value;
    }
}

public class TestMain{
    public static void main(String args[]){
        MyClass mc=new MyClass(10);
        System.out.println(mc.value);
    }
}

根据上述代码,选择正确答案:

A. 编译通过,输出10;

B. 编译不通过,把第2行挨骂改为final int value=10;

C. 编译不通过,把第4行代码改为public MyClass(){value=10;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/695714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用XLSX.utils.sheet_to_json()解析excel,给空的单元格赋值为空字符串

前言 今天用到XLSX来解析excel文件,调用XLSX.utils.sheet_to_json(worksheet),发现如果单元格为空的话,解析出来的结果,就会缺少相应的key(如图所示)。但是我想要单元格为空的话,值就默认给空字…

BUUCTF刷题之路--ez_pz_hackover_20161

检查开启的保护: 32位程序,没有开启保护。看到这大概率猜到是可以利用shellcode。接着IDA查看下逻辑: 主函数: header函数: chall函数: 大致讲解下程序逻辑。首先会要求你输入一个名字。存入s这个缓冲区中。…

Redis7【④ 事务 管道】

1. Redis事务 Redis 事务(Transaction)是一组 Redis 命令的集合,这些命令被当作一个整体,按顺序地串行化执行,而不会被其他命令插入。 Redis 事务使用 MULTI、EXEC、WATCH、DISCARD 和 UNWATCH 这些命令来实现。 1.1…

Linux系统:进程控制

文章目录 1 创建进程2 进程终止2.1 进程退出情况2.2 进程终止的常见方式2.2.1 return语句2.2.2 exit()函数2.2.3 _exit()函数 3进程等待3.1 进程等待的重要性3.2 进程等待的方法3.2.1 wait()方法3.2.2 waitpid()方法 4 进程替换4.1 替换原理4.2 替换函数 1 创建进程 fork()函数…

mediapipe 手势节点识别自动控制音量

参考:https://www.computervision.zone/topic/volumehandcontrol-py/ 主函数: VolumeHandControl.py import cv2 import time import numpy as np import HandTrackingModule as htm import math from ctypes import cast, POINTER from comtypes imp…

[问题解决] ubuntu 18.04 GPU驱动安装

删除当前显卡驱动[参考] sudo apt-get purge nvidia* 查看推荐驱动 sudo ubuntu-drivers devices 安装对应驱动 sudo apt install nvidia-driver-530 验证安装是否成功:nvidia-smi

「一本通 3.2 例 3」架设电话线

题目大意 在加权无向图上求出一条从 号结点到 号结点的路径,使路径上第 大的边权尽量小。 思路 由于是一次性的,且这题数据极小,考虑 正常情况下是来更新数组的,不过这次是更新 表示第个节点,(可以…

springboot引入外部sdk,以及在maven中配置,以及连同sdk打包

目录 1 安置sdk 2 配置maven配置文件 3 刷新maven即可 4 打包配置 1 安置sdk 将外部的sdk放在项目的指定目录下,我选择放在resource/sdk的目录下 示例: 2 配置maven配置文件 打开pom.xml,新增以下的依赖配置 具体如下所示: …

C# OpenCvSharp 透视变换(图像摆正)Demo

效果 Demo下载 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using OpenCvSharp; using OpenCvSha…

王爽《汇编语言》期末考试题库(附答案)

单选题 第一章 PC机的最小信息单位是( )。 A. bit B. 字节 C. 字长 D. 字 A PC机的最小信息单位是比特(bit),常用来表示一位二进制数字(0或1)。字节(byte)是计算机中常用的数据单位,一个字…

vscode中ModuleNotFoundError: No module named ‘torch‘解决方法

文章目录 遇到的问题解决方法参考 遇到的问题 使用vscode训练模型,没有使用远程服务器,使用本地运行代码,显示“ModuleNotFoundError: No module named ‘torch’” 解决方法 这是因为没有选择合适的python解释器。如何选择正确的解释器呢&…

【HDFS实战】HDFS上的数据均衡

HDFS上的数据均衡简介 文章目录 HDFS上的数据均衡简介重新平衡数据节点之间的数据块相关命令 重新平衡DN内磁盘间的数据相关命令PlanExecuteQueryCancelReport 相关配置调试 HDFS上的balance目前有两类: Balancer:节点之间的balanceDisk Balancer&#x…

C# WinForm 学习记录

1.为项目添加dll引用 在“解决方案资源管理器”面板中选择项目,单机鼠标右键,弹出菜单中选择“添加”->“引用”打开引用管理器,选择浏览添加自己需要的dll文件即可 2.位移运算符使用技巧 在进行位移运算时,当数值的二进制数…

设计模式学习笔记——你真的学透单例模式了吗

你真的学透单例模式了吗 一、概述 单例模式(Singleton Pattern)指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点,属于创建型设计模式 二、类图 三、通用写法 public class SingletonTest {public static vo…

使用docker安装redis,修改密码

1、搜索镜像 docker search redis 2、拉取镜像 docker pull redis 3.创建容器 前边是宿主机端口 后面是docker使用的端口 docker run --name redis -p 6379:6379 redis-test --requirepass 123456 这里密码设置为123456 4、如何修改密码 现有的redis创建密码或修改密码…

Python学习——字符串

一、字符串 字符串也是基本数据类型,是一个不可变的字符序列,字符串可以用单引号,双引号,三引号进行定义。 字符串的驻留机制,简而言之,就是相同的字符串只保留一个,后续创建相同字符串的时候&a…

【漏洞案例】云上攻防-记一次打穿云上内网的攻防实战

0x01 外网打点,但在云上 目标单位就给出了一个子域名和一个IP,访问给出的子域名就一个登录框,测试了下忘记密码处有用户名枚举,但登录功能做了登录失败处理,知道用户名也无法进行爆破。 登录时会调用api.target.com域…

CICflowmeter安装使用

项目地址:https://github.com/ahlashkari/CICFlowMeter前置条件:maven,winpcap或其他抓包工具,ideal或 Eclipse 用 ideal 打开项目,发现还需要 jnetpcap 包,但是 maven 仓库好像没有,自己编译 …

思科(Cisco)日志分析工具

作为网络安全管理员,实时监控和分析思科防火墙日志至关重要。对于安全网络,管理员需要: 检测各种网络攻击,并查明攻击的来源和类型(思科实时日志查看器)。跟踪思科防火墙上未经授权的登录尝试。获取有关活…

PHP OA协同办公管理系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP OA协同办公管理系统 是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 代码下载 https://download.csdn.net/download/qq_41221322/87959360https://do…