final的一个重要用途-宏变量和未初始化问题

/**
 * @author 张家琛
 * @version 1.0
 * @date 2023/1/24 20:23
 */
public class FinalDemo {
    public static void main(String[] args) {
        final var a=5;
        System.out.println(a);
    }
}

对于上面的程序来说,变量a其实根本就不存在,这段代码本质上执行的是转换成的:

        System.out.println(5);

final修饰符的一个重要用途就是定义“宏变量”,final变量有了初始值且可以在编译的时候就确定下来,那么它就是个“宏变量”,编译器会把程序中所有用到该变量的地方直接替换成该变量的值

再看一段代码

public static void main(String[] args) {
        //宏变量
        final var a = 7 + 8;
        final var b = 5.8 / 6;
        final var str = "final" + "关键字";
        final var book = "final关键字" + 66.66;
        //不会当成宏变量来处理,因为调用了方法,编译时确定不下来这个值是多少
        final var book2 = "final关键字" + String.valueOf(66.66);

        System.out.println(book=="final关键字66.66");
        System.out.println(book2=="final关键字66.66");
    }

 输出结果:

 如果被赋的表达式只是基本的算数表达式或字符串连接运算,没有访问普通变量和方法,Java编译器会将它当成宏变量来处理

即使book变量进行的是隐式字符串连接转换,但编译器仍然可以在编译时就确定下来book的值,因此a,b,str,book都是宏变量

所以,book会被编译器直接替换成"final关键字66.66",输出true

反之book2在编译的时候确定不下来到底是个啥值,得经过方法调用,就不是宏变量咯,不会让它指向字符串连接池中已经缓存好的"final关键字66.66"

再看下面程序

public static void main(String[] args) {
        var s1 = "海城你刀哥";
        var s2 = "海城" + "你刀哥";
        System.out.println(s1 == s2);

        var str1 = "海城";
        var str2 = "你刀哥";

        var s3 = str1 + str2;
        System.out.println(s1 == s3);
    }

输出结果

 

 对于s3而言,它是由str1和str2进行连接运算后得到,由于str1、str2只是两个普通变量,编译器不会执行宏替换,因此无法在编译时确定s3的值,也就无法让s3指向字符串常量池中缓存的”海城你刀哥“,固s1==s3为false

final修饰的成员变量未初始化的时候,到底能不能访问呢?

/**
 * @author 张家琛
 * @version 1.0
 * @date 2023/1/24 20:50
 */
public class FinalUnassignedTest {
    final int age;
    {
        System.out.println(age);
    }

    public static void main(String[] args) {
        new FinalUnassignedTest();
    }
}

运行结果:

 说明这种方式不太可行,如果换种形式:

public class FinalUnassignedTest {
    final int age;
    {
        printAge();
        age=6;
        System.out.println(age);
    }
    public void printAge(){
        System.out.println(age);
    }
    public static void main(String[] args) {
        new FinalUnassignedTest();
    }
}

输出结果:

刀哥来了也得寻思一会啊!!!!怎么先输出了个0???不是说没事先定义好的final不能输出吗??

其实Java是允许通过方法来访问final成员变量的,默认给了个0。但是这显然违背了final成员变量的设计初衷,所以建议别这么干,不然刀哥友情提醒:”有你好果纸吃“。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

服务端相声演员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值