Java类中final/static修饰的成员变量初始化问题

问题1:final修饰基本数据类型(final修饰成员变量的初始化方法)

1.代码

  • 问下述代码能否编译通过
public class Demo01 {

    private final int a;

    private String name;

    public Demo01(){
        a = 3;
    }

    public Demo01(String name){
        this.name = name;
    }

}

2.分析

  • 上述代码无法编译通过

在这里插入图片描述

  • 关于final修饰的成员变量的初始化有两种方法

    • 1.在定义的时候就赋予一个值
    • 2.在构造函数中完成初始化,因为当实例化该类的一个对象的时候,一定会调用一个构造方法,但是这也带来了一个问题,就是我们无法事先知道,会调用哪一个构造方法,如果采用这种方式,就一定要保证在每一个构造函数中都对该final变量进行初始化
  • 修改上述代码,在每一个构造函数中都对final修饰的变量初始化后可以正常编译
    在这里插入图片描述

问题2:final修饰静态成员变量的初始化方法

1.代码

  • 问下述代码能否编译通过,一个静态的final变量的初始化问题
public class Demo01 {

    private static final int a;

    private String name;

    public Demo01(){
        a = 3;
    }

    public Demo01(String name){
        a = 3;
        this.name = name;
    }

}

2分析

  • 无法编译通过

在这里插入图片描述

  • 一个静态变量在类加载完之后,实例化为对象之前就被加载了,而此时又被final修饰,所以必须要求有值!,所以这种情况下只能显式的进行初始化
  • 如果把代码改成下述看能否编译通过呢?

3.问题2.1

public class Demo01 {

    private static final int a = 3;

    private String name;

    public Demo01(){
        a = 3;
    }

    public Demo01(String name){
        a = 3;
        this.name = name;
    }

}
  • 也无法编译通过
    在这里插入图片描述

  • 至于原因,图中提示得很清楚了,不能给一个final修饰的变量赋值

  • 因为在构造方法一定会被调用的,所以一定会发现给一个final修饰的变量赋值的情况,所有只有改成下面的方式才可以编译通过

在这里插入图片描述

问题3:final修饰引用类型的初始化以及注意点

1.代码

  • 问下述代码能否编译通过
public class Demo02 {
    
    public static final StringBuffer s = new StringBuffer();
    
    public static void main(String[] args){
        s.append("hello");
    }
    
}

2分析

  • 可以编译通过
    在这里插入图片描述

  • 对于final修饰的引用类型变量来说,不变指的是引用不变,而不是这个引用指向的对象内容不变

  • 这个也很容易理解,final修饰的是引用s,这个s是什么呢?就是指向内存中某个对象的地址,所以这个地址不能变。但是这个地址对应的对象中的内容,是否改变,final这个修饰符就鞭长莫及了,管不到那么宽的

  • 所以,问下述代码能否编译通过

public class Demo02 {

    public static final StringBuffer s = new StringBuffer();

    public static void main(String[] args){
//        s.append("hello");
        s = new StringBuffer();
    }

}
  • 显然是不能的,s的地址变了
    在这里插入图片描述

问题4:为什么对于一个public类型的final的成员变量,一般都要声明为static的?

  • 为了节省内存
    在这里插入图片描述

  • static修饰的变量,在对象创建之前,类加载之后就在内存里了,而且不管这个类被实例化为了多少个对象,内存都只有这一个变量

  • 如果不被static修饰,仅仅是final修饰,那么创建100个对象,这个变量就会在内存中有100份,而被final修饰的初衷就是拿来读的,所以只需要1份就够了


版权声明:本文为fat_cai_niao原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。