Java中的final变量、final方法和final类

2023-05-16

1、final变量

final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。例如,在类中定义PI值,可以使用如下语句:

final double PI=3.14;

在Java中定义全局常量,通常使用public static final修饰,这样的常量只能在定义是被赋值。

public static final double PI_VAULE = 3.14;

规范:被定义为final的常量定义时需要使用大写字母命名,并且中间使用下划线进行连接。

常量示例:

import java.util.Random;

class Test
{
	int i = 0;
}

/**
 * 常量示例
 * 
 * @author pan_junbiao
 *
 */
public class FinalData
{
	static Random rand = new Random();
	private final int VALUE_1 = 9; // 声明一个final常量
	private static final int VALUE_2 = 10; // 声明一个final、static常量
	private final Test test = new Test(); // 声明一个final引用
	private Test test2 = new Test(); // 声明一个不是final的引用
	private final int[] a = { 1, 2, 3, 4, 5, 6 }; // 声明一个定义为final的数组
	private final int i4 = rand.nextInt(20);
	private static final int i5 = rand.nextInt(20);

	public String toString()
	{
		return "i4值:" + i4 + " i5值:" + i5 + " ";
	}

	public static void main(String[] args)
	{
		FinalData data = new FinalData();

		// 报错:不能改变定义为final的常量值
		// data.VALUE_1 = 8;

		// 报错:不能改变定义为final的常量值
		// data.VALUE_2 = 9;

		// 报错:不能将定义为final的引用指向其他引用
		// data.test = new Test();

		// 正确: 可以对指定为final的引用中的成员变量赋值
		data.test.i = 1;

		// 正确: 可以将没有定义为final的引用指向其他引用
		data.test2 = new Test();

		// 报错:不能对定义为final的数组赋值
		// int b[] = { 7, 8, 9 };
		// data.a = b;

		// 但是final的数组中的每一项内容是可以改变的
		for (int i = 0; i < data.a.length; i++)
		{
			data.a[i] = 9;
		}

		System.out.println(data);
		System.out.println("data2");
		System.out.println(new FinalData());
	}
}

执行结果:

 

从上述执行结果中可以发现i5的值是相同的。

全局常量:

我们知道一个被定义为final的对象引用只能指向唯一一个对象,不可以将它再指向其它对象,但是一个对象的值却是可以改变的,那么为了使一个常量真正做到不可更改,可以将常量声明为static final。

示例:在项目中创建FinalStaticData类,在该类中创建Random类的对象,在主方法中分别输出类中定义的final变量a1与a2。

import static java.lang.System.out;

import java.util.Random;

/**
 * FinalStaticData类
 * 
 * @author pan_junbiao
 *
 */
public class FinalStaticData
{
	private static Random rand = new Random(); // 实例化一个Random类对象
	// 随机产生0~10之间的随机数赋予定义为final的a1
	private final int a1 = rand.nextInt(10);
	// 随机产生0~10之间的随机数赋予定义为static final的a2
	private static final int a2 = rand.nextInt(10);

	public static void main(String[] args)
	{
		FinalStaticData fdata = new FinalStaticData(); // 实例化一个对象
		// 调用定义为final的a1
		out.println("重新实例化对象调用a1的值:" + fdata.a1);
		// 调用定义为static final的a2
		out.println("重新实例化对象调用a2的值:" + fdata.a2);
		// 实例化另外一个对象
		FinalStaticData fdata2 = new FinalStaticData();
		out.println("重新实例化对象调用a1的值:" + fdata2.a1);
		out.println("重新实例化对象调用a2的值:" + fdata2.a2);
	}
}

运行结果:

 

从本示例运行结果中可以看出,定义为final的常量不是恒定不变的,将随机数赋予定义为final的常量,可以做到每次运行程序时改变a1的值。但是a2与a1不同,由于它被声明为static final形式,所以在内存中为a2开辟了一个恒定不变的区域,当再次实例化一个FinalStaticData对象时,仍然指向a2这块内存区域,所以a2的值保存不变。a2是在装载时被初始化,而不是每次创建新对象时被初始化;而a1会重新实例化对象时被更改。

最后总结一下在程序中final数据可以出现的位置,如下程序。

/**
 * 总结一下在程序中final数据可以出现的位置
 * 
 * @author pan_junbiao
 *
 */
public class FinalDataTest
{
	// final成员变量不可更改
	final int VALUE_ONE = 6;

	// 在声明final成员变量时没有赋值,称为空白final
	final int BLANK_FINALVAULE;

	// 在构造方法中为空白final赋值
	public FinalDataTest()
	{
		BLANK_FINALVAULE = 8;
	}

	// 设置final参数,不可以改变参数x的值
	int doIt(final int x)
	{
		return x + 1;
	}

	// 局部变量定义为final,不可以改变i的值
	void doSomething()
	{
		final int i = 7;
	}
}

 

2、final方法

首先,我们应该了解定义为final的方法不能被重写

将方法定义为final类型可以防止任何子类修改该类的定义与实现方式,同时定义为final的方法执行效率要高于非final方法。在修饰权限中曾经提到过private修饰符,如果一个父类的某个方法被设置为private修饰符,子类将无法访问该方法,自然无法覆盖该方法,所以一个定义为private的方法隐式被指定为final类型,这样无须将一个定义为private的方法再定义为final类型。

语法:

private final void test()
{
}

 

3、final类

定义为final的类不能被继承。

如果希望一个类不允许任何类继承,并且不允许其他人对这个类有任何改动,可以将这个类设置为final形式。

final类的语法如下:

final 类名{}

如果将某个类设置为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。

示例:在项目中创建FinalClass类,在类中定义doit()方法和变量a,实现在主方法中操作变量a自增。

/**
 * 定义final类
 * 
 * @author pan_junbiao
 *
 */
final class FinalClass
{
	int a = 3;

	void doit()
	{
	}

	public static void main(String args[])
	{
		FinalClass f = new FinalClass();
		f.a++;
		System.out.println(f.a); // 结果:4
	}
}

 

4、总结

下面总结了一些使用final关键字的好处:

(1)final关键字提高了性能。JVM和Java应用都会缓存final变量。

(2)final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。

(3)使用final关键字,JVM会对方法、变量及类进行优化。

不可变类:

创建不可变类要使用final关键字。不可变类是指它的对象一旦被创建了就不能被更改了。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销等等。

关于final的重要知识点:

(1)final关键字可以用于成员变量、本地变量、方法以及类。

(2)final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。

(3) 你不能够对final变量再次赋值。

(4)本地变量必须在声明时赋值。

(5)在匿名类中所有变量都必须是final变量。

(6)final方法不能被重写。

(7)final类不能被继承。

(8)final关键字不同于finally关键字,后者用于异常处理。

(9)final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。

(10)接口中声明的所有变量本身是final的。

(11)final和abstract这两个关键字是反相关的,final类就不可能是abstract的。

(12)final方法在编译阶段绑定,称为静态绑定(static binding)。

(13)没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。

(14)将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。

(15)按照Java代码惯例,final变量就是常量,而且通常常量名要大写。
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中的final变量、final方法和final类 的相关文章

  • Java EE 6 和单例

    谁能解释一下在 Java EE 6 应用程序中实现 Singleton 的完整过程 我假设我不应该以声明静态变量的典型方式创建单例 而应该使用 Singleton注解 我必须这样做吗 难道只是声明一下的情况 Singleton就是这样 我还
  • 我在使用 JavaFX 绘制十字时遇到问题

    我正在尝试编写代码 在网格上对角绘制 3 个形状 前两个形状是正方形和圆形 我能做到 然而 第三种形状让我有些悲伤 我应该画一个十字 T 版本 而不是 X 每次我写出代码时 它看起来就像一个侧面 我知道我只是错过了一些简单的东西 但我真的很
  • Hibernate 每个子类一个表继承策略的效率

    我正在考虑 Hibernate 管理的类层次结构的表布局 当然 每个子类表技术在我看来是一般意义上最合适的 然而 通过逻辑思考 我对其性能有些担忧 尤其是随着子类数量的扩展 举一个非常简短 且经典 的示例 假设您有以下类 public ab
  • 使用 JavaScript 与 Web 服务器通信的 Applet 是否可以迁移到 JWS?

    只是分享一些信息 希望对社区有用 由于各种浏览器停止支持插件 Applet 的可用性已经下降 Google 已决定停止对 NPAPI 插件的支持 EDGE 不支持插件 Firefox 也不鼓励使用插件 Mozilla 可能会跟进该套件 我们
  • 如何在JavaFX中有效地滚动和缩放大图像?

    作为图像处理应用程序的一部分 我需要创建具有缩放 滚动和矢量叠加功能的简单查看器模块 图像相当大 40000x20000 这使得 ImageView 上的操作变慢 缓冲等 在 JavaFX 中处理巨大图像时 改善用户体验的最佳选项是什么 我
  • 解析 (yyyy-MM-dd) 格式的字符串日期

    我有一个 2013 09 18 形式的字符串 我想将其转换为 java util Date 我正在做这个 SimpleDateFormat sdf new SimpleDateFormat yyyy MM dd Date converted
  • Grails 项目 - Servlet 调用 - ClassNotFoundException:javax.servlet.AsyncContext

    我在用 IntelliJ IDEA 终极版 12 4 grails 2 2 0 BuildConfig groovy 文件中的 grails servlet version 2 5 并实现了简单的 servlet post 请求 使用 RE
  • Eclipse 无法识别 persistence.xml 的内容

    我在 eclipse 中收到以下错误 persistence xml 文件没有可识别的内容 我的 persistence xml 文件在我的应用程序中工作得很好 但 eclipse 一直给我这个错误 我在移动文件并使用 m2eclipse
  • JTree ConvertValueToText 返回在更改时被截断

    我有一个自定义树实现convertValueToText 此实现取决于某些全局状态 如果返回的字符串比先前返回的字符串更长 实际上我认为更宽 因为以像素为单位触发它 则文本将被截断并用 填充 当重绘是由 取消 选择元素或某个元素引起时 情况
  • 为什么不自动装箱泛型的 Java 基本类型?

    Java 不允许在通用数据结构中使用原始类型 例如 不允许使用 ArrayList 原因是 原始类型不能直接转换为Object 然而 Java 1 5 确实支持自动装箱 并且包装类在通用数据结构中工作 那么为什么编译器不能将其自动装箱到 A
  • Java 声音可视化器

    我正在尝试制作一个java声音可视化工具 但我完全不知道如何在实时处理音频后立即从提取的音频中获取字节 我可以将程序与 wav 文件同步 但这不是我想要做的 我想用程序生成声音 然后播放它 而不将其保存在任何地方 谢谢您的帮助 本文可以帮助
  • 不使用 length() 方法的字符串长度[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 如何在不使用字符串的情况下找到字符串的长度length String类的方法 str toCharArray length应该管用 或者怎么
  • java中永远不会出现的异常

    我为点和向量编写一个类 我想用它们来计算向量的点和范数 这些是点类和向量类 public class Point public float x y public class MyVector public Point start end 我
  • 将 Maven 控制台与 m2eclipse 一起使用

    Maven 新手在这里 有没有办法在 Eclipse 中打开控制台并在 M2Eclipse 插件上执行 Maven 命令 这是一个非常好的插件 但我环顾四周 没有找到我想要的一些功能 谢谢 如果你想运行特定的maven插件 你可以这样做 g
  • SQlite 获取最近的位置(带有纬度和经度)

    我的 SQLite 数据库中存储有纬度和经度的数据 我想获取距我输入的参数最近的位置 例如我当前的位置 纬度 经度等 我知道这在 MySQL 中是可能的 并且我已经做了相当多的研究 SQLite 需要一个自定义外部函数来实现半正弦公式 计算
  • Web 服务客户端的 AXIS 与 JAX-WS

    我决定用Java 实现Web 服务客户端 我已经在 Eclipse 中生成了 Axis 客户端 并使用 wsimport 生成了 JAS WS 客户端 两种解决方案都有效 现在我必须选择一种来继续 在选择其中之一之前我应该 考虑什么 JAX
  • 如何从 Sublime Text 编辑器调试 Java 应用程序

    有时我正在对相当大的 Java 应用程序进行简单的修复 但我不想打开 Eclipse 来执行此任务 Eclipse 启动时间很长 并且由于该项目是由大量子项目构建的 而这些子项目无论如何都是由 Maven 构建的 因此需要很长时间才能使用
  • 对于双核手机,availableProcessors() 返回 1

    我最近购买了一部 Moto Atrix 2 手机 当我尝试查看手机中的处理器规格时 Runtime getRuntime availableProcessors 返回 1 proc cpuinfo 也仅包含有关处理器 0 的信息 出于好奇
  • 在 servlet 会话和 java.io.NotSerializedException 中保存对象

    SEVERE IOException while loading persisted sessions java io WriteAbortedException writing aborted java io NotSerializabl
  • removeall 和removeif 的用例

    我找到了这个 fun main val list MutableList

随机推荐

  • rosdep init 错误的终极解决方法

    rosdep init 错误的终极解决方法 从网站上下载需要的文件 xff1a https github com Vision4UAV rosdistro tree master rosdep 将文件夹和五个文件下载下来 拷贝到 etc r
  • vs2017调用dll文件提示“LNK2019 无法解析的外部符号 “__declspec(dllimport) public: __cdecl ”解决方法

    如题 xff0c 通过vs2017定义的接口生成了dll文件并调用测试结果报错无法解析的外部符号 解决方法 xff1a 在C C 43 43 目录中包含dll对应的头文件 xff0c 库目录包含dll文件 xff0c 如下图所示 然后在链接
  • matlab使用app designer进行界面开发时,给控件的显示值进行赋值时,提示‘Text‘ 或‘Value‘ 必须为字符向量或字符串标量的解决办法

    使用 xff1a sprintf 39 s 39 taskID 进行变量值的格式化 如下图 xff1a 以及 xff1a
  • Chrome安装zotero connector 插件

    1 下载zotero connector插件 ZoteroConnectorv5 0 68 zip 其它文档类资源 CSDN下载 2 找到crx文件 xff0c 重命名为rar然后解压 3 打开扩展应用安装界面 4 打开开发者模式 xff0
  • 2011年工作总结---测试流程梳理

    主要针对半年测试工作中测试流程的梳理 根据各项目测试任务过程中自己的总结和学习 xff0c 这里介绍下测试各阶段的注意点 虽然以前也对测试各个阶段做了总结 xff0c 但是感觉很散很乱 xff0c 这里就整合一下以前的总结 xff0c 根据
  • 生成随机数的两种方法

    一 Math random 方法 它会生成一个大于等于0 0且小于1 0 0 0 1 0 的double类型的数字 public static void main String args 案例1 System out println 34
  • UnBBayes考虑时序因素时的推理

    最近在使用UnBBayes进行MEBN的研究 xff0c 有时候推理需要考虑上一时刻的状态 一开始总是无法产生前一时刻状态的节点 当加入证据 t pre 61 pretimeOf t now 后就可以正常出现上一时刻的状态的节点了
  • zotero文献管理软件插件配置终极教程

    zotero是一款开源免费的文献管理工具 xff0c 在各位大神制作的插件加持下 xff0c 对于我来说已经没有满足不了的文献管理需求了 xff01 xff01 xff01 现将zotero使用教程整理如下 首先感谢贡献zotero和zot
  • ROS多机器人时rviz无法显示机器人模型,提示:param robot_description not found by searchParam()

    如图所示 xff0c 使用ROS进行多机器人仿真时 xff0c RobotModel无法显示机器人模型 xff0c 提示 xff1a param robot description not found by searchParam 原因 x
  • xcode使用gdal库

    GDAL Geospatial Data Abstraction Library 是一个在X MIT许可协议下的开源栅格空间数据转换库 它利用抽象数据模型来表达所支持的各种文件格式 它还有一系列命令行工具来进行数据转换和处理 GDAL提供对
  • MAC系统版本AnyLogic提示the font “Times“ is not available

    问题原因 xff1a MAC新版本系统中移除了Times字体 导致JAVA运行出现问题 如图所示为需要安装的Times字体 解决方法 xff1a 重新安装TImes字体 下载地址
  • LIBTIFF读取tiff文件时,打印buf出错

    如图所示 xff0c 按照官网提供的例程读取tiff文件 xff0c 并打印读取的值时 xff0c 提示 xff1a Subscript of pointer to incomplete type 39 void 39 代码如下 xff1a
  • OHEM loss 源代码

    import numpy as np import torch import torch nn as nn class OhemCELoss nn Module def init self thresh ignore lb 61 255 s
  • git命令回退方法

    我们在使用git命令的时候 xff0c 有时候误输入命令 xff0c 导致需要回退到之前的状态 现在针对这种情况做一个汇总 xff1a 1 Git add回退 git status 先看一下add中的文件 xff0c 确定已经添加的文件 g
  • 思岚激光雷达A1使用

    1 使用思岚调试激光雷达测试软件 xff08 软件打开前和打开后雷达都是转动的 xff09 点击菜单栏上的扫面按钮 xff0c 扫描出周围的环境轮廓 方向和距离定义 测试完成 xff0c 关闭雷达测试软件 2 使用串口调试助手测试 测试A1
  • STM32读取MPU6050陀螺仪

    目录 一 硬件设计 1 模块说明 2 电气原理图 二 程序设计 1 工程创建 2 程序设计 xff08 1 xff09 main程序 xff08 2 xff09 IIC初始化 xff08 3 xff09 串口1配置 xff08 4 xff0
  • kalibr标定IMU

    kalibr标定IMU 必须明确的是 1 如何标定 2 标定的结果 3 如何验证标定结果的正确性 如何标定 标定所需文件 XX bag 包含有图片信息和IMU数据的ROS包 camchain yaml 包含相机的内参和畸变参数的文件 IMU
  • git diff和回退操作

    在git提交环节 xff0c 存在三大部分 xff1a working tree index file commit 这三大部分中 xff1a working tree xff1a 就是你所工作在的目录 xff0c 每当你在代码中进行了修
  • 基于Python socket利用TCP协议让上下位机 传输图片

    基于Python socket利用TCP协议让上下位机 传输图片 Notes 1 原理2 下位机代码 xff1a 3 上位机代码 xff1a Notes 之前用来做 基于QT 的物联网图形化软件的其中一个功能 xff0c 因为在这遇到过许多
  • Java中的final变量、final方法和final类

    1 final变量 final关键字可用于变量声明 xff0c 一旦该变量被设定 xff0c 就不可以再改变该变量的值 通常 xff0c 由final定义的变量为常量 例如 xff0c 在类中定义PI值 xff0c 可以使用如下语句 xff