[转载] Java中的final变量、final方法和final类
参考链接: Java中的final数组 | Final arrays
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变量就是常量,而且通常常量名要大写。
[转载] Java中的final变量、final方法和final类相关推荐
- Java中的PrintWriter的write方法和print方法的区别是什么?
参考:https://www.zhihu.com/question/511719621
- Java中static、this、super、final用法
一.static 请先看下面这段程序: public class Hello{ public static void main(String[] args){ //(1) System.out.pri ...
- [转载] Java中变量与常量
参考链接: Java中的实例变量隐藏 1.变量的定义:定义变量就是要告诉编译器这个变量的数据类型,这样编译器才知道需要分配多少空间给它,以及它能存放什么样的数据.在程序运行过程中空间的值是变化的,这个 ...
- [转载] Java中的变量和常量
参考链接: Java中的变量范围 在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量. 在 ...
- Java中的宏变量,宏替换详解。
转载自 Java中的宏变量,宏替换详解. 群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 输出true false 来看下面这段程序,和群友分享的大致一样. public static vo ...
- [转载] Java中如何引用另一个类里的集合_Java工程师面试题整理
参考链接: 在Java中将预定义的类名用作类或变量名 花了一星期把学过的都整理一遍 尽量易懂,从基础到框架 最新版大厂面经汇总出炉,持续更新中 汇总完了上传网盘,设计到后端架构师的一切知识 如果没更新 ...
- 【Groovy】Groovy 动态语言特性 ( Groovy 中的变量自动类型推断以及动态调用 | Java 中必须为变量指定其类型 )
文章目录 前言 一.Groovy 动态语言 二.Groovy 中的变量自动类型推断及动态调用 三.Java 中必须为变量指定其类型 前言 Groovy 是动态语言 , Java 是静态语言 ; 一.G ...
- 非静态方法可以访问Java中的静态变量/方法吗?
"非静态方法可以访问静态变量或调用静态方法"是Java中有关静态修饰符的常见问题之一,答案是, 是的 ,非静态方法可以访问静态变量或调用静态方法. Java中的方法. 这没有问题, ...
- java中的实例变量
简介 在类的声明中,属性是用变量来表示的.这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的.类的每个对象维护它自己的一份实例变量的副本. java中的实例变量 含义: 实例变量 ...
最新文章
- 利用cmake查看OpenCV的源码的方法
- sdut 1028 Catch That Cow( BFS)
- html5中标签分为,HTML标签的三种类型
- 2021牛客暑期多校训练营7 K-xay loves sequence(主席树+二分)
- 为Openstack制作CentOS7镜像
- BMW M550i xDrive
- ECharts实操手册
- Matlab中的有限域计算
- 苹果计算机怎样恢复桌面,mac桌面整理_使Mac桌面恢复整洁的四种技巧
- choco 代理强制失效方法
- unity简单实现融合树动画
- 求解线性同余方程--扩展欧几里得
- 避暑山庄消失的三十六景,曾经那么美!
- python数据分析六个环节_安利6个珍藏的Python数据分析神器
- 【08月20日】A股滚动市净率PB历史新低排名
- 利用 a 标签 实现 下载图片(不是打开)的正确姿势
- Jenkins密码忘记重置方法
- 算法题 —— 寻找明星
- SDUT 3929 魔戒
- Leetcode 334.递增的三元子序列
热门文章
- 让div垂直以及水平居中浏览器窗口
- 一个android工程生成两个aar,android studio生成aar包并在其他工程引用aar包(示例代码)...
- PyTorch中的torch.nn.Parameter() 详解
- memcpy和memmove的区别以及内存重叠问题
- 海南大学计算机原理,海南大学微机原理课件 第一章 计算机基础知识
- wireshark网卡权限_网络分析系列之六_Wireshark安装
- 你用计算机做过什么事情,他偷偷干了什么?(电脑)
- Problem E: 建立链表(线性表)
- HDU1284——钱币兑换问题【dp】
- Flutter 使用动画播放一组图片