深入java final关键字 用法注意点和JVM对其进行的优化(例子)

本文深入探讨final关键字在Java中的使用规范及JVM对其优化机制。包括final变量的声明与初始化规则、final static作为常量时的JVM优化,以及final变量的不可变性等关键知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇文章我们总结了final关键字的基本用法和优点,这一篇文章我们继续深入,总结开发中遇到的使用final关键字需要注意的地方和JVM对final关键字的优化。我们用例子说明,原创不易,转载请注明出处:http://blog.youkuaiyun.com/yabay2208

(按照Java代码惯例,final变量就是常量,而且通常常量名要大写:)
- final关键字声明的static变量(属于类)必须在声明、类初始化(static{})的时候初始化,而且不能重复赋值;而非static变量(属于对象),必须在声明、对象初始化({}方法)或者构造函数里面初始化,也不可以重复赋值。(有例子)
- final static作为常量的时候,jvm会对其进行优化(有例子)
- final变量不可变的是句柄的地址,其实里面的值可以改变(有例子)

一:final变量的声明和初始化

final关键字声明的static变量(属于类)必须在声明、类初始化(static{})的时候初始化,我们举一个例子说明:

/**
 * @author yangwuyi
 */

class Final{
    static final String I = "helloworld";
    static {
        System.out.println("Final's static function!类初始化。。。。。。");
        //I = "helloWorld";
    }
}

或者:

/**
 * @author yangwuyi
 */

class Final{
    static final String I ;
    static {
        System.out.println("Final's static function!类初始化。。。。。。");
        I = "helloWorld";
    }
}



但是对于而非static的final变量(属于对象),必须在声明、对象初始化({}方法)或者构造函数里面初始化,也不可以重复赋值。我们举一个例子说明:

/**
 * @author yangwuyi
 */

class Final {
    final String S = "two";

    {
        System.out.println("Final's function!对象初始化。。。。。。");
        //S = "hello;";
    }

    public Final(String helloWorld) {
        //S = helloWorld;
    }
}

或者

/**
 * @author yangwuyi
 */

class Final {
    final String S ;

    {
        System.out.println("Final's function!对象初始化。。。。。。");
        S = "hello;";
    }

    public Final(String helloWorld) {
        //S = helloWorld;
    }
}

或者

/**
 * @author yangwuyi
 */

class Final {
    final String S ;

    {
        System.out.println("Final's function!对象初始化。。。。。。");
        //S = "hello;";
    }

    public Final(String helloWorld) {
        S = helloWorld;
    }
}

而且有一点都要记住:都不可以重复赋值。

二:final static作为常量的时候,jvm会对其进行优化

一个类中有声明为static final的变量,jvm会对类的加载进行优化,先来看一个对比的例子:
这里写图片描述
运行结果:
这里写图片描述s
解析:因为s是static final变量,且它等于helloWorld,在编译的时候就可以知道它的值,所以直接访问s的值不会引起Final类的初始化。作为表现,也就是static静态代码块不会被加载。


第二:
这里写图片描述
运行结果:

解析:因为s是static final变量,因为s在编译的时候无法知道它的确切的值,所以只有等到运行的时候才能知道,所以访问s的值会引起Final类的初始化。作为表现,也就是static静态代码块会被加载。

三:final变量不可变的是句柄的地址,其实里面的值可以改变

还是通过例子来说明问题。

/**
 * @author yangwuyi
 */
public class FinalTest {
    public static final List TEMPEXM = new ArrayList();

    public static void main(String[] args) {
        FinalTest.TEMPEXM.add("hello ");
        FinalTest.TEMPEXM.add("world !");
        System.out.println(FinalTest.TEMPEXM);
    }
}

运行结果:
这里写图片描述
final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。

第二个例子:

/**
 * @author yangwuyi
 */
class Final{
    static int i = 0;
}

public class FinalTest {
    public static void main(String[] args) {
        Final f = new Final();
        changFinalClass(f);
    }
    public static void changFinalClass(final Final f) {
        //f = new Final();//出错
        f.i = 100;
    }
}

目的是不允许将引用变量进行重定向,但是引用的值却是可以变化的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值