文章目录
问题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版权协议,转载请附上原文出处链接和本声明。