修改final属性值-内联优化

总结:Java 编译器会对 final 修饰且类型为基本类型(byte、char、short、int、long、 float、 double、 boolean、String [直接双引号字符串])属性做内联优化,编译时直接把该 final 的值放到了引用它的地方。即使是反射修改了该属性值,但在后续使用中还是旧值。只要不被编译器内联优化的 final 属性值都可以通过反射进行修改(修改后使用的是新值)
准备验证代码:
public class Service {
    public final static int a = 11;
    public final static Integer b = 22;

    public static int getA() {
        return a;
    }

    public static Integer getB() {
        return b;
    }

    public void sayA() {
        if (a == 111) {
            System.out.println("updated a");
        } else {
            System.out.println("old a");
        }
    }

    public void sayB() {
        if (b == 222) {
            System.out.println("updated b");
        } else {
            System.out.println("old b");
        }
    }
}

                
<think>好的,我现在需要解释Javafinal修饰属性。首先,我得回忆一下final关键字在Java中的用法,特别是当它用于属性时的具体行为。 首先,final属性指的是这个变量一旦被初始化后就不能再被修改。这点我记得没错,但需要确认具体细节。比如,不同的数据类型是否表现一致,比如基本类型和引用类型。对于基本类型,final确实会让值不可变,而引用类型的话,对象的内容可能还能变,但引用本身不能指向其他对象。这点可能需要举例说明,比如一个final的数组,数组元素可以修改,但数组引用不能指向另一个数组。 然后,初始化方式。final属性可以在声明时初始化,或者在构造方法中初始化。如果是静态的final属性(即类变量),则必须在声明时或静态初始化块中赋值。这点很重要,特别是区分实例变量和类变量的不同初始化要求。 还需要提到空白final变量(blank final),也就是声明时未初始化,但在构造器中必须初始化的实例变量。这样可以让不同对象拥有不同的final值,例如每个实例的某个属性可以根据构造器参数确定,之后不可变。 另外,final属性在多线程中的安全性,可能是一个高级话题,但用户可能想知道。比如,final变量可以确保构造过程中的正确初始化,避免其他线程看到未完全初始化的对象,从而保证线程安全。不过用户的问题可能更基础,这部分可能不需要深入,但可以稍微提及。 此外,使用final修饰属性的一些最佳实践,比如使代码更清晰、不可变性有助于减少错误等。可能可以举一些例子,比如定义常量时通常用public static final组合,这时候命名规范是大写加下划线。 需要确保语法正确,比如final的位置,例如可以写成final int x = 5;或者static final double PI = 3.14;。同时,注意是否必须初始化,如果在声明时未初始化,构造器中必须处理,否则编译错误。 可能存在的误区是,有人认为final修饰的引用类型对象内容也不可变,但实际上只是引用不可变。比如,final List<String> list = new ArrayList<>();,之后list.add("item")是允许的,但list = new ArrayList<>();会报错。这一点需要明确说明,避免误解。 总结结构的话,可能先定义final属性的基本作用,然后分点讨论初始化方式、基本类型和引用类型的区别,空白final变量,静态final属性,以及使用final的好处和注意事项。这样结构清晰,逐步深入,帮助用户理解。</think>在Java中,`final`关键字用于修饰属性时,表示该属性一旦被赋值后**不可再修改**。以下是关于`final`修饰属性的详细介绍: --- ### 一、基本特性 1. **不可变性** -属性是**基本类型**(如`int`, `double`),其**值**不可变。 示例: ```java final int x = 10; x = 20; // 编译错误!无法修改final基本类型属性的值 ``` -属性是**引用类型**(如对象、数组),其**引用地址**不可变,但对象内部的状态可能可变。 示例: ```java final List<String> list = new ArrayList<>(); list.add("Java"); // 允许操作对象内部状态 list = new LinkedList<>(); // 编译错误!无法修改引用地址 ``` 2. **必须初始化** - `final`属性必须在以下时机之一初始化: - **声明时直接赋值** ```java final int MAX_VALUE = 100; ``` - **构造方法中赋值**(适用于实例变量) ```java class MyClass { final int x; public MyClass(int x) { this.x = x; // 必须在构造方法中初始化 } } ``` - **静态初始化块**(适用于`static final`类变量) ```java class Constants { static final double PI; static { PI = 3.14159; // 静态初始化块中赋值 } } ``` --- ### 二、特殊用法 1. **空白final(Blank Final)** - 指声明时未初始化,但在构造方法中初始化的实例变量。 示例: ```java class Person { final String name; // 声明时未初始化(空白final) public Person(String name) { this.name = name; // 构造方法中初始化 } } ``` 2. **静态常量(static final)** - 通常用于定义全局常量,需在声明时或静态初始化块中赋值。 示例: ```java public class MathConstants { public static final double PI = 3.141592653589793; public static final double E = 2.718281828459045; } ``` --- ### 三、使用场景与优势 1. **保证不可变性** - 防止属性被意外修改,提升代码安全性。 2. **明确设计意图** - 通过`final`明确告知其他开发者该属性不可变。 3. **线程安全** - `final`属性在对象构造完成后即完全初始化,多线程环境下无需额外同步即可安全访问。 4. **优化性能** - JVM可能对`final`属性进行优化(如内联常量值)。 --- ### 四、注意事项 1. **引用类型的内容可变性** - `final`仅限制引用地址,不限制对象内部状态。 示例: ```java final int[] arr = {1, 2, 3}; arr[0] = 4; // 允许修改数组元素 arr = new int[5]; // 编译错误! ``` 2. **避免在构造方法外初始化** - 非静态`final`属性若未在声明时初始化,必须在**所有构造方法**中赋值,否则编译失败。 --- ### 五、总结 | 类型 | 初始化时机 | 是否可修改 | |---------------------|------------------------------|-------------------------| | 实例变量(非静态) | 声明时或构造方法中 | 引用地址不可变,内容可能可变 | | 类变量(静态) | 声明时或静态初始化块中 | 同实例变量 | 合理使用`final`修饰属性,能增强代码的健壮性和可读性,尤其适合定义常量和需要不可变状态的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值