全面解析java final关键字
作者:Spear_J 发布时间:2023-03-16 03:04:55
根据上下文环境,Java 的关键字 final 的含义有些微的不同,但通常它指的是“这是不能被改变的”。防止改变有两个原因:设计或效率。因为这两个原因相差很远,所以有可能误用关键字 final。
以下几节讨论了可能使用 final 的三个地方:数据、方法和类。
1)final 数据
对于编译时常量这种情况,编译器可以把常量带入计算中,可以减少了一些运行时的负担。在 Java 中,这类常量必须是基本类型,而且用关键字 final 修饰。你必须在定义常量的时候进行赋值。
带有恒定初始值的 final static 基本变量(即编译时常量)命名全部使用大写,单词之间用下划线分隔。
一个被 static 和 final 同时修饰的属性只会占用一段不能改变的存储空间。
当用 final 修饰对象引用而非基本类型时,
对于基本类型,final 使数值恒定不变。
对于对象引用,final 使引用恒定不变。
一旦引用被初始化指向了某个对象,它就不能改为指向其他对象。但是,对象本身是可以修改的,Java 没有提供将任意对象设为常量的方法。(你可以自己编写类达到使对象恒定不变的效果)这一限制同样适用数组,数组也是对象。
示例:
import java.util.*;
class Value {
int i;
Value(int i) {
this.i = i;
}
}
/**
* @author Limh
*/
public class FinalData {
private static Random rand = new Random(47);
private String id;
public FinalData(String id) {
this.id = id;
}
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
public static final int VALUE_THREE = 39;
private final int i4 = rand.nextInt(20);
static final int INT_5 = rand.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(22);
private static final Value VAL_3 = new Value(33);
private final int[] a = {1, 2, 3, 4, 5, 6};
@Override
public String toString() {
return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
}
public static void main(String[] args) {
FinalData fd1 = new FinalData("fd1");
//v2=new Value(22);
fd1.v2.i++;
fd1.v1 = new Value(9);
//a.length = 6
for (int i = 0; i < fd1.a.length; i++) {
fd1.a[i]++;
}
System.out.println(fd1);
System.out.println("Creating new FinalData");
FinalData fd2 = new FinalData("fd2");
System.out.println(fd1);
System.out.println(fd2);
}
}
输出:
fd1: i4 = 15, INT_5 = 18
Creating new FinalData
fd1: i4 = 15, INT_5 = 18
fd2: i4 = 13, INT_5 = 18
因为第一个变量和第二个变量都是带有编译时值的 final 基本类型,它们都可用作编译时常量,没有多大区别。第三个变量是一种更加典型的常量定义的方式:public 意味着可以在包外访问,static 强调只有一个,final 说明是一个常量。
正如你在 main() 中所见,v2 是 final 的并不意味着你不能修改它的值。因为它是引用,所以只是说明它不能指向一个新的对象。
2)空白final
空白 final 指的是没有初始化值的 final 属性。
编译器确保空白 final 在使用前必须被初始化。这样既能使一个类的每个对象的 final 属性值不同,也能保持它的不变性。
你必须在定义时或在每个构造器中执行 final 变量的赋值操作。这保证了 final 属性在使用前已经被初始化过。
3)final参数
在参数列表中,将参数声明为 final 意味着在方法中不能改变参数指向的对象或基本变量:
class Gizmo {
public void spin() {
}
}
/**
* @author Limh
*/
public class FinalArguments {
void with(final Gizmo g) {
//-g = new Gizmo();
// Illegal -- g is final
}
void without(Gizmo g) {
g = new Gizmo(); // OK -- g is not final
g.spin();
}
//void f(final int i) { i++; } // Can't change
// You can only read from a final primitive
int g(final int i) {
return i + 1;
}
public static void main(String[] args) {
FinalArguments bf = new FinalArguments();
bf.without(null);
bf.with(null);
}
}
4) final方法
使用 final 方法的原因有两个。
给方法上锁,防止子类通过覆写改变方法。这是出于继承的考虑,确保方法的行为不会因继承而改变。
只有在为了明确禁止覆写方法时才使用 final。
5) final和private
类中所有的 private 方法都隐式地指定为 final。因为不能访问 private 方法,所以不能覆写它。
6)final类
当说一个类是 final (final 关键字在类定义之前),就意味着它不能被继承。之所以这么做,是因为类的设计就是永远不需要改动,或者是出于安全考虑不希望它有子类。
由于 final 类禁止继承,类中所有的方法都被隐式地指定为 final,所以没有办法覆写它们。你可以在 final 类中的方法加上 final 修饰符,但不会增加任何意义。
来源:https://www.cnblogs.com/lmh15054109/p/14306823.html


猜你喜欢
- 本文实例为大家分享了JSON处理工具类的具体代码,供大家参考,具体内容如下import java.io.IOException; impor
- /** * 三角数字: * 比达哥斯拉领导下的古希腊数学家发现了一个有趣的数字序列1, 3, 6, 10, 15, 21,... *
- 一、概述简单理解为 异步消息插队并优先执行。场景:排队买票先来了一个普通用户来排队,买完票走了。后面又来了一个VIP用户A来买票 就一直站在
- GridView是类似于ListView的控件,只是GridView可以使用多个列来呈现内容,而ListView是以行为单位,所以用法上是差
- 本文实例为大家分享了QT实现简单计算器功能的具体代码,供大家参考,具体内容如下效果图:新建工程,创建类MainWindow,基类是QMain
- 日志是非常重要的,虽然他不会以需求功能提来,但也不会体现在产品方案中。但是,它在系统项目中却占有巨大的地位。为了保证服务的高可用,发现问题一
- 将IDEA的默认快捷键设置 设置成为 Eclipse的默认快捷键设置题意有些拗口,但没关系,就是将idea中的快捷键转为自己刚学Java时使
- 1、产生原因其实显示黑屏或者白屏实属正常,这是因为还没加载到布局文件,就已经显示了window窗口背景,黑屏白屏就是window窗口背景。示
- 通过一个变量控制线程中断代码:package com.itsoku.chat05;import java.util.concurrent.T
- =====最大线程数====linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_THREADS_MAX这个限制可以在 /u
- Application对象Application对象生存期和Web应用程序生存期一样长,生存期从Web应用程序网页被访问开始,HttpApp
- 上次介绍了位置服务中的Geocoder,这次就来介绍一下LocationManager。LocationManager系统服务是位置服务的核
- 本文介绍了Android TextView属性ellipsize多行失效的解决思路,分享给大家,具体如下:多余文字显示省略号的常规做法and
- 问题一次面试遇到的一个问题,其实也是实际开发中很容易遇到的问题,特此记录一下。当请求某个接口的时候,我们会在请求的header中携带toke
- 写在前面很久以前就听nice0e3师傅说打Fastjson可以试试C3P0,当时还不会java(虽然现在也没会多少)也就没有深究。最近调试F
- @ApiModel使用场景在实体类上边使用,标记类时swagger的解析类概述提供有关swagger模型的其它信息,类将在操作中用作类型时自
- 使用开源框架是,可以直接复制源代码到自己的项目(本人在Android Studio中操作报R程序包不存在),也可以使用jar包,下面记录一下
- 本文实例讲述了Java自定义注解用法。分享给大家供大家参考,具体如下:一 自定义注解语法[public] @interface Annota
- 一:什么是协变与逆变协变指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,逆变指能够使用比原始指定的派生类型的派生程度更小(不
- 发送虚拟请求访问controller我们在test类中虚拟访问controller,就得发送虚拟请求。先创建一个controllerpack