一、变量初始化相关
成员变量有默认值,局部变量完全无默认值(最大误区)
新手错觉:所有变量不用赋值也能使用。
真相:
- 类成员(实例变量、静态变量):系统自动赋默认值(数值0、布尔false、对象null);
- 方法内局部变量:不会自动初始化,不手动赋值直接使用编译报错。
反常识:哪怕是int a;局部变量,打印、运算都会报错,不会默认给0。
初始化顺序:静态 > 实例 > 构造器,构造器不是最先执行
执行顺序:
静态变量赋值 → 静态代码块 → 实例变量赋值 → 实例代码块 → 构造方法
坑:在构造器里读取静态变量没问题,但如果静态代码块依赖还未加载的实例,会出现null/0异常。
父类静态内容先于子类所有代码执行
子类new对象时:先执行父类静态、再子类静态;再父类实例、父构造,最后子类实例、子类构造。
易错:以为子类静态比父类先初始化。
二、构造器相关反常识坑
子类构造器默认隐式调用父类无参构造super(),且必须第一行
- 父类只写了带参构造、无无参构造时,子类不写super(参数)直接编译报错;
- super()必须放在构造方法第一行,前面不能写任何代码。
构造器没有返回值,不能写void/任何返回类型
新手容易误写void Test(){},这不再是构造器,只是普通方法,new时不会执行。
构造器可以私有(单例模式),普通方法不行靠私有实现单例
反常识:构造器修饰符支持private,禁止外部new本类对象。
三、final三重语义极易混淆(本章重点坑)
- final 基本变量:值不可修改;
- final 引用变量:引用地址不能变,但对象内部属性可以改(大坑);
例:final List<Integer> list = new ArrayList<>(); list.add(1); 合法,只是不能list = 新集合。 - final 方法:不能被子类重写;
- final 类:禁止继承。
四、代码块(静态块/实例块)易错点
实例代码块每次new对象都会执行;静态代码块仅类加载执行1次
误区:以为静态块每次创建实例都会跑。
实例代码块可以访问实例变量,静态代码块不能直接访问非静态成员
静态块中调用实例属性/实例方法,编译报错。
五、清理、垃圾回收、finalize(经典反常识)
finalize() 不可靠,绝对不能用来释放资源
新手误区:重写finalize关闭流、数据库连接。
真相:JVM不保证finalize一定会执行,执行时机不确定,OOM时可能直接跳过,生产环境禁止依赖。
对象不会立刻被GC,没有手动销毁对象的语法
没有类似C++ delete关键字,把引用置为null只是帮助GC,不代表立即回收。
循环内创建大量对象,不会立刻释放,容易内存堆积
新手以为循环结束对象自动消失,短期大量创建会造成GC频繁。
六、数组初始化坑
int[] arr2; // 成员变量,默认null
int[] arr3 = new int[5]; // 数组内每个元素默认0
易错:直接操作成员数组arr2[0],报空指针。
七、方法参数初始化、重载构造器
构造器互相调用this(参数),同样必须放在第一行,且不能和super共存
一个构造器要么this调用本类其他构造,要么super调用父类,二者只能选其一。
初始化表达式、代码块先于构造器执行
实例变量赋值、{}实例块,都在构造器代码之前运行。
陷阱:构造器修改了同一个变量,会覆盖前面初始化的值。
八、隐藏小反常识点
基本类型包装类成员变量默认是null,不是0
Integer num; // 成员默认null
int num2; // 成员默认0
直接调用num.intValue() 空指针,新手高频bug。
静态变量属于类,所有实例共享一份
修改任意对象的静态变量,全部对象读取都会变化,很多人误以为每个实例独立一份。
九、习题巩固
第1题
题目:下列关于变量默认初始化说法正确的是?
A. 方法内局部int变量默认值为0
B. 类的实例Integer成员变量默认值为0
C. 静态成员变量会自动赋予默认初始值
D. 局部对象变量默认值为null
正确答案:C
解析:
A 错误:局部变量无默认值,不赋值直接使用编译报错;
B 错误:Integer是包装类引用,成员默认null,不是0;
C 正确:静态变量、实例成员变量都会由JVM自动赋予默认初始值;
D 错误:局部引用变量没有默认值,不存在自动null。
第2题
题目:类初始化执行顺序正确的是?
A. 实例变量 → 静态代码块 → 构造器
B. 静态变量赋值 → 静态代码块 → 实例变量赋值 → 实例代码块 → 构造器
C. 构造器最先执行
D. 实例代码块先于静态代码块执行
正确答案:B
解析:
类加载阶段先处理静态相关:静态变量赋值 → 静态代码块(仅执行一次);
创建对象时执行实例相关:实例变量赋值 → 实例代码块 → 构造方法。
A、C、D顺序全部颠倒错误。
第3题
题目:关于final修饰引用变量,代码final List<String> list = new ArrayList<>();下列操作合法的是?
A. list = new ArrayList<>();
B. list.add(“test”);
C. list = null;
D. list.clear()之外所有修改集合的操作都报错
正确答案:B
解析:
final修饰引用变量,限制的是引用地址不可变,不限制对象内部内容修改。
A、C:试图重新赋值list引用,编译报错;
B:往集合添加元素,修改集合内部,完全合法;
D:错误,add、remove、clear等修改集合元素都允许。
第4题
题目:子类构造器相关描述错误的是?
A. 子类构造第一行默认隐式调用super()
B. super()与this()不能同时出现在一个构造器内
C. 若父类只有带参构造,子类不写super(参数)也能编译通过
D. this()调用本类其他构造必须放在方法第一行
正确答案:C
解析:
A:正确,子类构造器首行默认隐藏super()调用父类无参构造;
B:正确,super()和this()都要求放在第一行,二者无法共存;
C:错误,父类不存在无参构造时,子类必须手动写super(对应参数),否则编译报错;
D:正确,this()调用同类其他构造必须放在构造方法第一行。
第5题
题目:有关静态代码块与实例代码块说法正确的是?
A. 每次new对象都会执行静态代码块
B. 静态代码块可以直接访问实例成员变量
C. 实例代码块在构造器代码执行前运行
D. 实例代码块仅在类加载时执行一次
正确答案:C
解析:
A 错:静态代码块只在类加载时执行1次,多次new不会重复执行;
B 错:静态上下文无法直接访问实例成员,编译报错;
C 对:实例变量赋值、实例代码块{} 都在构造器内部代码之前执行;
D 错:实例代码块每次创建对象都会执行。
第6题
题目:关于finalize()方法,描述正确的是?
A. 可以依靠finalize释放文件、数据库连接等资源
B. JVM一定会在对象回收前执行finalize()
C. finalize执行时机完全不可控,不能用于资源清理
D. 对象置为null后会立刻触发finalize执行
正确答案:C
解析:
A 错误:finalize执行时机不确定,甚至可能不执行,不能用来释放资源;
B 错误:JVM不保证finalize一定执行,内存耗尽时可能直接丢弃对象;
C 正确;
D 错误:引用置null只是让对象可被GC,不会立刻触发回收与finalize。
第7题
题目:下列代码会编译报错的是?
A. 构造方法 private Test(){}
B. void Test(){}
C. Test(){super();}
D. Test(){int a = 10;}
正确答案:B
解析:
A:构造器可以用private修饰,用于单例,合法;
B:void Test(){} 带有返回值void,不再是构造方法,只是普通成员方法,该写法会导致new时不会执行这个方法,属于典型错误写法;
C:构造器第一行写super()显式调用父类无参构造,合法;
D:构造器内先定义局部变量,无问题。
第8题
题目:下面关于成员变量默认值说法错误的是?
A. int 实例成员变量默认值为0
B. Boolean 静态成员变量默认值为null
C. boolean 实例成员变量默认值为false
D. Integer局部变量默认值为null
正确答案:D
解析:
A 正确:基本类型int成员默认0;
B 正确:Boolean是包装类,引用类型成员默认null;
C 正确:基本boolean成员默认false;
D 错误:局部变量没有任何默认值,不会自动赋值null,直接使用编译报错。
第9题
题目:下列关于构造器中 this() 描述正确的是?
A. this() 可以写在构造方法任意一行
B. 一个构造器可以同时调用 this() 和 super()
C. this() 作用是调用本类其他构造方法
D. 静态方法里可以使用 this()
正确答案:C
解析:
A 错误:this() 必须放在构造器第一行,前面不能写任何代码;
B 错误:this() 和 super() 都要求首行,二者不能共存;
C 正确;
D 错误:this、this() 都依赖实例,静态方法没有实例,无法使用。
第10题
题目:有如下代码结构,创建子类对象时执行顺序正确的是?
class Parent{
static {System.out.println(“父静态块”);}
{System.out.println(“父实例块”);}
Parent(){System.out.println(“父构造”);}
}
class Son extends Parent{
static {System.out.println(“子静态块”);}
{System.out.println(“子实例块”);}
Son(){System.out.println(“子构造”);}
}
A. 父静态块 → 子静态块 → 父实例块 → 父构造 → 子实例块 → 子构造
B. 父静态块 → 父实例块 → 父构造 → 子静态块 → 子实例块 → 子构造
C. 子静态块 → 父静态块 → 父实例块 → 父构造 → 子实例块 → 子构造
D. 父静态块 → 子静态块 → 子实例块 → 子构造 → 父实例块 → 父构造
正确答案:A
解析:
完整顺序对应选项A。
第11题
题目:下列描述错误的是?
A. 静态代码块只能访问静态变量、静态方法
B. 实例代码块可以访问静态成员
C. 局部基本变量不赋值也能直接打印
D. 引用类型成员变量默认值为null
正确答案:C
解析:
A 正确:静态上下文没有实例,不能直接访问实例成员,只能访问静态;
B 正确:实例代码块同时持有类与实例上下文,静态成员可随意访问;
C 错误:局部变量无默认值,不赋值直接使用编译报错;
D 正确:所有引用类型成员变量默认初始值都是null。
第12题
题目:代码:final Integer num = 10; 后续操作合法的是?
A. num = 20
B. Integer temp = num;
C. num = null
D. num++
正确答案:B
解析:
final修饰基本类型变量,变量存储的值不可修改。
A:num=20 试图重新赋值final变量,编译报错;
B:Integer temp = num; 只是拷贝数值,完全合法;
C:给final变量赋null,编译报错;
D:num++等价于num = num + 1,修改final变量,编译报错。
核心知识点:final修饰基本变量,值全程不能修改,只能读取,不能二次赋值、自增自减。
第13题
题目:以下关于数组初始化说法错误的是?
A. int[] arr; 作为成员变量,默认值为null
B. int[] arr = new int[3]; 数组内部每个元素默认0
C. Integer[] arr; 局部变量,直接调用arr[0]不会报错
D. Integer[] arr = new Integer[2]; 数组元素默认null
正确答案:C
解析:
A 正确:数组是引用类型,成员变量默认null;
B 正确:基本类型数组元素默认值为0;
C 错误:arr是局部变量,无默认值,未赋值直接使用编译报错;
D 正确:包装类数组内部元素默认null。
第14题
题目:下面关于静态变量特点描述正确的是?
A. 每个对象都拥有一份独立静态变量
B. 修改任意实例的静态变量,所有实例读取结果都会变化
C. 静态变量只能在静态代码块中赋值
D. 静态变量不具备默认初始值
正确答案:B
解析:
A 错误:静态变量属于类,全局共享,不存在每个实例独立副本;
B 正确;
C 错误:静态变量可直接定义时赋值、静态块赋值;
D 错误:静态成员变量会自动赋予默认值。




