final修饰的变量

article/2025/9/23 14:10:15

被final修饰的实例变量必须显式指定初始值,而且只能在如下3个位置指定初始值.

1.定义final实例变量时指定初始值;

2.在非静态初始化块中为final实例变量指定初始值;

3.在构造器中为final实例变量指定初始值.

对于普通实例变量,Java程序可以对它执行默认的初始化,也就是将实例变量的值指定为默认的初始值0或null;但对于final实例变量,则必须由程序显式指定初始值.

package com.lic.array;
public class FinalInstanceVaribaleTest {
public static void main(String[] args) {
FinalInstanceVaribaleTest fiv = new FinalInstanceVaribaleTest();
System.out.println(fiv.var1);
System.out.println(fiv.var2);
System.out.println(fiv.var3);
} 
// 定义final实例变量时赋初始值
final int var1 = "疯狂Java讲义".length();
final int var2;
final int var3;
// 在初始化块中为var2赋初始值
{
var2 = "轻量级Java EE企业应用实战".length();
}
// 在构造器中为var3赋初始值
public FinalInstanceVaribaleTest(){
this.var3 = "疯狂XML讲义".length();
}
}
上面的程序定义了3个final修饰的实例变量.var1,var2,var3,分别在定义是时为var1赋初始值,在初始化块中为var2指定初始值,在构造器中为var3指定初始值.但是经过编译器的处理,这三种方式都会抽取到构造器中赋初始值.如果使用javap工具来分析:

Compiled from "FinalInstanceVaribaleTest.java"
public class com.lic.array.FinalInstanceVaribaleTest {final int var1;final int var2;final int var3;public static void main(java.lang.String[]);Code:0: new           #1                  // class com/lic/array/FinalInstance
VaribaleTest3: dup4: invokespecial #2                  // Method "<init>":()V7: astore_18: getstatic     #3                  // Field java/lang/System.out:Ljava/
io/PrintStream;11: aload_112: getfield      #4                  // Field var1:I15: invokevirtual #5                  // Method java/io/PrintStream.printl
n:(I)V18: getstatic     #3                  // Field java/lang/System.out:Ljava/
io/PrintStream;21: aload_122: getfield      #6                  // Field var2:I25: invokevirtual #5                  // Method java/io/PrintStream.printl
n:(I)V28: getstatic     #3                  // Field java/lang/System.out:Ljava/
io/PrintStream;31: aload_132: getfield      #7                  // Field var3:I35: invokevirtual #5                  // Method java/io/PrintStream.printl
n:(I)V38: returnpublic com.lic.array.FinalInstanceVaribaleTest();Code:0: aload_01: invokespecial #8                  // Method java/lang/Object."<init>":
()V4: aload_05: ldc           #9                  // String 疯狂Java讲义7: invokevirtual #10                 // Method java/lang/String.length:()
I10: putfield      #4                  // Field var1:I13: aload_014: ldc           #11                 // String 轻量级Java EE企业应用实战16: invokevirtual #10                 // Method java/lang/String.length:()
I19: putfield      #6                  // Field var2:I22: aload_023: ldc           #12                 // String 疯狂XML讲义25: invokevirtual #10                 // Method java/lang/String.length:()
I28: putfield      #7                  // Field var3:I31: return
}
从上面分析结果可以看出:final实例变量必须显式地被赋初始值,而且本质上final实例变量只能在构造器中被赋初始值.当然,就程序员变成来说,还可在定义final实例变量时指定初始值,也可以初始化块中为final实例变量指定初始值,但它们本质上是一样的.除此之外,final实例变量将不能被再次赋值.

对于final类变量而言,同样必须显式指定初始值,而且final类变量只能在2个地方指定初始值:

1.定义final类变量时指定初始值;

2.在静态初始化块中为final类变量指定初始值.

package com.lic.array;public class Demo22 {// 定义final类变量时赋初始值final static int var1 = "疯狂Java讲义".length();final static int var2;// 在静态初始化块中为var2赋初始值static{var2 = "轻量级Java EE企业应用实战".length();}public static void main(String[] args) {System.out.println(Demo22.var1);System.out.println(Demo22.var2);}}
上面程序中定义了2个final类变量var1和var2,在定义var1时为其赋初始值,在静态初始化块中为var2指定初始值.需要指出的是,经过编译器的处理,这2中方式都会被抽取到静态初始化块中赋初始值.如果使用javap工具来肥西改程序:

Compiled from "Demo22.java"
public class com.lic.array.Demo22 {static final int var1;static final int var2;public com.lic.array.Demo22();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":
()V4: returnpublic static void main(java.lang.String[]);Code:0: getstatic     #2                  // Field java/lang/System.out:Ljava/
io/PrintStream;3: getstatic     #3                  // Field var1:I6: invokevirtual #4                  // Method java/io/PrintStream.printl
n:(I)V9: getstatic     #2                  // Field java/lang/System.out:Ljava/
io/PrintStream;12: getstatic     #5                  // Field var2:I15: invokevirtual #4                  // Method java/io/PrintStream.printl
n:(I)V18: returnstatic {};Code:0: ldc           #6                  // String 疯狂Java讲义2: invokevirtual #7                  // Method java/lang/String.length:()
I5: putstatic     #3                  // Field var1:I8: ldc           #8                  // String 轻量级Java EE企业应用实战10: invokevirtual #7                  // Method java/lang/String.length:()
I13: putstatic     #5                  // Field var2:I16: return
}
上面程序为final类变量赋初始值.可以看到,var1,var2两个类变量的赋初始值过程都是放在静态初始化块内完成的.由此可见,final类变量必须显式地被赋初始值,而且本质上final实例变量只能在静态初始化块中被赋初始值.当然就程序员编程来说,还可在定义final类变量时指定初始值.也可以在静态初始化块中为final类变量指定初始值,但它们本质上是一样的.除此之外,final类变量将不能被再次赋值.

final修饰局部变量的情形则比较简单----Java本来就要求局部变量必须被显式地赋初始值,final修饰的局部变量一样需要被显式的赋初始值.与普通初始变量不同的是:final修饰的局部变量被赋初始值之后,以后再也不能对final局部变量重新赋值.

经过上面介绍,大致可以发现final修饰符的第一个简单功能:被final修饰的变量一旦被赋初始值,final变量的值以后将不会被改变.

除此之外,final修饰符还有一个功能.

package com.lic.array;public class Demo23 {public static void main(String[] args) {// 通过Price的INSTANCE访问currentPrice实例变量System.out.println(Price_23.INSTANCE.currentPrice);// 显式创建Price实例Price_23 p = new Price_23(2.8);// 通过显式创建的Price实例访问currentPrice实例变量System.out.println(p.currentPrice);}}
class Price_23{// 类成员是Price实例final static Price_23 INSTANCE = new Price_23(2.8);// 再定义一个类变量final static double initPrice = 20;// 定义该Price的currentPrice实例变量double currentPrice;public Price_23(double discount){// 根据静态变量计算实例变量currentPrice = initPrice - discount;}
}
你猜输出啥?

很明显,这是程序中增加了final修饰符的缘故.再次使用javap工具来分析下:

Compiled from "Demo23.java"
class com.lic.array.Price_23 {static final com.lic.array.Price_23 INSTANCE;static final double initPrice;double currentPrice;public com.lic.array.Price_23(double);Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: ldc2_w        #3                  // double 20.0d8: dload_19: dsub10: putfield      #5                  // Field currentPrice:D13: returnstatic {};Code:0: new           #2                  // class com/lic/array/Price_233: dup4: ldc2_w        #6                  // double 2.8d7: invokespecial #8                  // Method "<init>":(D)V10: putstatic     #9                  // Field INSTANCE:Lcom/lic/array/Price_23;13: return
}
如果不使用final修饰程序中的initPrice类变量,看看javap的分析结果
Compiled from "Demo23.java"
class com.lic.array.Price_23 {static final com.lic.array.Price_23 INSTANCE;static double initPrice;double currentPrice;public com.lic.array.Price_23(double);Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: getstatic     #2                  // Field initPrice:D8: dload_19: dsub10: putfield      #3                  // Field currentPrice:D13: returnstatic {};Code:0: new           #4                  // class com/lic/array/Price_233: dup4: ldc2_w        #5                  // double 2.8d7: invokespecial #7                  // Method "<init>":(D)V10: putstatic     #8                  // Field INSTANCE:Lcom/lic/array/Price_23;13: ldc2_w        #9                  // double 20.0d16: putstatic     #2                  // Field initPrice:D19: return
}
对比上面两个输出结果,不难发现当使用final修饰符变量时,如果定义该final类变量时指定了初始值,而且该初始值可以在编译时就被确定下来,系统将不会在静态初始化块中对该类变量赋初始值,而将是在类定义中直接使用该初始值代替该final变量.

对于一个使用final修饰的变量而言,如果定义该final变量时就指定初始值,而且这个初始值可以在编译时就确定下来,那么这个final变量将不再是一个变量,系统会将其当成"宏变量"处理.也就是说,所有出现该变量的地方,系统将直接把它当成对应的值处理.

对于上面的Price类而言,由于使用了final关键字修饰initPrice类变量,因此Price类的构造器中执行currentPrice = initPrice - discount; 代码时,程序直接会将initPrice替换成20.因此,执行该代码的效果相当于currentPrice = 20 - discount;.


http://chatgpt.dhexx.cn/article/8HSBUmuS.shtml

相关文章

Java中的final变量 final修饰变量 final修饰方法 final修饰类 final和String的关系

目录 引言final修饰变量final修饰变量&#xff0c;不可再改变量的值final修饰对象&#xff0c;能否修改对象属性值final全局静态变量 final修饰方法final修饰类重要总结final关键字的好处final的重要知识点 引言 在开发的过程中&#xff0c;经常会使用String类来处理字符串相关…

Java中final修饰变量

一:final修饰的变量即成为常量&#xff0c;只能赋值一次&#xff0c;但是final所修饰局部变量和 员变量有所不同。 (1)final修饰的局部变量必须使用之前被赋值一次才能使用 (2)final修饰的成员变量在声明时没有赋值的叫“空白final变量”,空白final变量必须在构造器方法或静态代…

微信服务商-小程序支付-商户传入的appid参数不正确,请联系商户处理

报错&#xff1a;商户传入的appid参数不正确&#xff0c;请联系商户处理。 处理方式&#xff1a; 1、 2、需要在商户号&#xff0c;配置小程序的APPID https://pay.weixin.qq.com/static/pay_setting/appid_protocol.shtml

支付宝APP支付之查看支付宝商户ID

2019独角兽企业重金招聘Python工程师标准>>> 1、登录支付宝蚂蚁金服开放平台 2、查看账号详情&#xff0c;选择合作伙伴管理&#xff0c;账户管理&#xff0c;查看角色身份&#xff0c;此处的PID就是商户ID 3、点击秘钥管理&#xff0c;可查看绑定的相关应用及其APP…

iOS-微信支付商户支付下单id非法

最近在APP中WKWebView中调用微信支付的时候&#xff0c;一直报商户支付下单id非法。看了n边微信文档&#xff0c;度娘了n次-----仍未解决。因为安卓的支付是没有问题的所以就跟安卓兄弟要了最终调用微信的字符串&#xff1a; weixin://wap/pay?prepayid%3Dwx19165520991244d92…

微信企业付款 ”错误码:NO_AUTH,错误信息:此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置“报错的处理办法

提示”错误码:NO_AUTH,错误信息:此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置“ 快速解决问题!!! 解说一下这个IP&#xff1a;这个IP是你发起支付的服务器外网IP&#xff0c;跟用户发起提现IP没关系&#xff0c;所以这里配置的是服务器IP。 这是微信官方给…

微信外部浏览器支付遇到:支付场景非法、appid 未关联paysignkey、商户支付下单id非法 等问题

正常流程用户支付完成后会返回至发起支付的页面&#xff0c;如需返回至指定页面&#xff0c;则可以在MWEB_URL后拼接上redirect_url参数&#xff0c;来指定回调页面。如&#xff0c;您希望用户支付完成后跳转至https://www.wechatpay.com.cn&#xff0c;则可以做如下处理&#…

微信的商户单号和交易单号_教你获取支付宝和微信的订单号、商户单号,涨知识了...

生活中常会用到支付宝和微信交易&#xff0c;交易完成后会用到「订单号」「商户单号」&#xff0c;需要注意的是微信的 「交易单号」就 等同于「订单号」&#xff0c;「订单号」和「商户单号」一般在同一个地方就能找到&#xff01;&#xff01;&#xff01; 获取支付宝「订单号…

微信支付商户平台,企业付款,企业向个人付款接口总结

这几天做项目&#xff0c;有个需求&#xff0c;是微信用户需要把公众号中赚的钱提现&#xff0c;于是查资料找到了微信商户平台中的高级业务&#xff1a;企业付款。 官方文档&#xff1a;https://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter14_1 为了以后方便看&am…

微信支付常见错误和统一下单错误码详情

微信支付常见错误和统一下单错误码详情 微信支付常见问题描述及解决方法微信调用统一下单接口&#xff0c;当result_codeFAIL时&#xff0c;错误代码及错误描述参考链接&#xff1a; 微信支付常见问题描述及解决方法 序号问题错误描述解决方法1此公众号并没有这些scope的权限&…

微信支付 ---- (商户号该产品权限处罚中)

微信支付 ---- &#xff08;商户号该产品权限处罚中&#xff09; 一、分析问题 今天星期天不情愿的来上班&#xff0c;刚坐下来准备吃一下我的小包子&#xff0c;客户爸爸就很核蔼来电话了~ 电话里面说微信小程序怎么不能支付了啊~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 我很淡…

小程序支付提示 商户号mch_id与appid不匹配 的解决

打开微信支付平台&#xff0c; 进入产品中心后&#xff0c; 点击关联更多Appid 之后填写小程序的appid即可。 appid 可以 从微信公众平台查看。 点开头像下拉即可看到appid填写完成后会提示 已成功发起APPID授权绑定申请 请提醒APPID管理员尽快确认申请请求 公众号(包括小程序…

小程序微信支付提示:商户订单号重复

最近在有用户反馈,点击订单结束无反应. 去后台看了看报错, 是这个样子的 <xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> <appid><![CDATA[保密处理]]></appid>…

【支付】第三方支付收单机构

简要概述 现在&#xff0c;在银行卡收单市场里&#xff0c;第三方收单机构在全国范围类极速发展。 收单牌照的第三方支付机构&#xff0c;即通过线下布放POS&#xff0c;替商户收单&#xff0c;第三方支付机构一般是找一个合作的收单银行&#xff0c;对于收单银行自己的持卡人…

小程序支付报错:向微信请求统一下单失败:商户号该产品权限未开通,请前往商户平台>产品中心检查后重试

一.检查微信商户和小程序是否建立绑定关系,没有绑定的需要进行绑定 1.登录微信商户平台,产品中心-->AppId账号管理-->关联AppId 2.填写要绑定的小程序AppId和认证主体点提交(可在微信公众平台-->设置-->基本设置获取) 3.登录微信公众平台 -->功能-->微信支付…

jenkins下载插件失败的解决方案

最近自己搭建jenkins&#xff0c;想实现远程部署环境&#xff0c;下载插件时提示失败&#xff0c;需要说明的是jenkins安装插件失败的原因是多样的&#xff0c;这里查找原因应该是镜像库地址的问题&#xff0c;以下是解决方案。 1.报错提示&#xff1a; 2.解决步骤&#xff1a…

Jenkins下载插件,报java.net.SocketTimeoutException: Read timed out

使用Jenkins下载插件报错 解决办法&#xff1a; 系统管理->插件管理->Advanced 选择最后的update site,输入http://mirror.esuni.jp/jenkins/updates/update-center.json 记得点submit 重新下载插件&#xff0c;即可成功 转载至&#xff1a;https://blog.csdn.net/qq_…

K8S搭建自动化部署环境(三)Jenkins下载、安装和启动

各位大佬&#xff0c;前文如下: K8S搭建自动化部署环境&#xff08;一&#xff09;安装Kubernetes K8S搭建自动化部署环境&#xff08;二&#xff09;安装K8S管理工具Kuboard V3 一、jenkins 下载 jenkins下载地址&#xff1a;https://jenkins.io/zh/download/ 如下图&…

修改 jenkins 插件下载地址

Jenkins国外官方插件地址下载速度非常慢&#xff0c;可以修改为国内的地址。 如下步骤&#xff1a; 到jenkins主机 cd /var/lib/jenkins/ //这个是jenkins的开发目录 cat updates/default.json //这里记录的是刚才从官方网站下载的所有插件地址12 修改…

jenkins 下载插件失败处理办法

jenkins 下载插件失败处理办法 jenkins 下载插件失败,提示&#xff1a; java.io.IOException: Downloaded file /app/jenkins_home/plugins/jacoco.jpi.tmp does not match expected SHA-1, expected CtK02wHdFOxTutqhUQzmue6uvpg, actual YGO05utKyaaFzpGCgCE95GS0WsUat hud…