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