公司动态
【小白学习系列】Java编程思想第7章趟坑笔记(二)
《Java编程思想》第7章「复用类」反常识新手高频易错点本章核心是组合、继承、构造器初始化、重写、向上转型、清理、代理下面按模块整理所有违背直觉、极易踩坑的点全部是书中原文重点坑。五、向上转型看似简单隐藏反常识逻辑1. 向上转型自动安全向下转型强制强转且有风险误区子类对象转父类会丢失功能真相向上转型只是缩小接口视图对象本体还是子类实例调用重写方法依然走子类只是父类不存在的方法无法直接调用要强转回来。2. 向上转型是继承的核心价值不是“附加功能”新手以为继承只是复用代码书中强调继承最重要的作用是向上转型实现多态代码复用只是附带收益。六、清理与垃圾回收颠覆C/C思维的反常识点1. Java无析构函数finalize不可靠不能依赖GC自动释放资源新手直觉对象不用了GC自动清理资源文件、流、连接书中结论GC只回收堆内存不处理IO、网络、文件句柄等系统资源finalize()执行时机不确定甚至永远不执行必须手动提供dispose()/close()清理方法搭配try-finally保证一定执行。2. 垃圾回收只和内存有关和对象生命周期业务清理完全无关很多新手混淆内存回收与资源释放导致文件句柄泄漏、连接占满。一、核心一句话GC只管堆内存里的对象空间不关文件流、数据库连接、Socket、句柄这类系统资源GC触发时机不可控千万别靠GC帮你关资源。二、错误示范依靠GC释放资源必泄漏importjava.io.FileReader;importjava.io.IOException;publicclassGcResourceTest{// 方法执行完毕reader变成局部垃圾对象publicvoidreadFile()throwsIOException{FileReaderreadernewFileReader(test.txt);char[]bufnewchar[1024];reader.read(buf);// 故意不写 reader.close()指望GC回收reader时自动关闭文件}publicstaticvoidmain(String[]args)throwsException{GcResourceTesttestnewGcResourceTest();for(inti0;i1000;i){test.readFile();}System.gc();// 手动建议GC依旧不靠谱Thread.sleep(2000);}}问题说明reader对象在方法结束后成为垃圾堆内存迟早会被GC清空但是文件句柄属于操作系统内核资源GC回收对象不会主动调用close关闭文件循环上千次打开文件不关闭最终直接抛出打开的文件过多系统异常造成句柄泄漏。三、正确写法手动释放资源try-with-resources 最优publicvoidreadFileCorrect(){// 实现AutoCloseable的资源代码块结束自动closetry(FileReaderreadernewFileReader(test.txt)){char[]bufnewchar[1024];reader.read(buf);}catch(IOExceptione){e.printStackTrace();}}四、配套直白总结GC职责归还JVM堆内存业务资源文件、连接、端口必须开发者手动主动释放finalize() 曾用来收尾资源现已被官方废弃完全不可信赖。七、protected访问修饰符极易理解偏差错误认知protected子类任意访问真实规则双重权限同包内所有类均可访问不同包只有子类能访问反常识跨包无关类哪怕名字相近也不能碰protected成员。八、静态方法不存在重写只有遮蔽大坑静态方法绑定引用类型不绑定实际对象classParent{publicstaticvoidtest(){System.out.println(父静态);}}classSonextendsParent{publicstaticvoidtest(){System.out.println(子静态);}}ParentpnewSon();p.test();// 输出父静态静态方法无多态看引用类型Parent新手误以为静态方法可以重写、支持多态完全错误这叫静态遮蔽。汇总新手最容易踩的Top5致命反常识坑子类同名父private方法以为重写多态完全失效父构造器中调用重写方法子类变量未初始化数据错乱无脑用继承复用代码忽略优先组合的设计原则混淆变量遮蔽与方法重写以为变量有多态依赖GC/finalize释放文件、网络资源造成资源泄漏。知识回炉重温向上转型 进一步解释寓言戏台演员完美对应向上转型人物父类身份【普通演员挂牌】子类本体【武生演员】武生自带两套本事所有演员都会的登台唱戏重写方法、自己独有的翻跟头子类独有方法故事剧情剧场规定入场登记只允许挂「普通演员」牌子进场。武生没办法挂上普通演员的牌子走入后台普通演员挂牌 真实武生本人→ 这就是向上转型。本体从没变化人从头到尾就是武生翻跟头、唱戏的本事全部都在身上半点没丢掉。被牌子限制了对外能力剧场喊所有人上台唱戏武生上台表演的是武生版唱腔动作执行子类重写方法你想让他当众翻跟头拿着“普通演员”这个牌子剧场系统不认翻跟头这项技能直接不让执行不是武生不会是牌子权限不够。想要翻跟头怎么办把挂牌换回「武生」身份向下强制转型才能解锁专属技能。对应继承的本质剧团设计不同演员分类继承体系首要目的是剧场只用“普通演员”一个入口就能收纳武生、花旦、老生所有演员入场管理多态。至于武生不用重新学习基础唱戏流程、共用舞台规则代码复用只是顺带的便利而已。一句话收尾向上转型本人没变只是证件降级通用行为照旧专属技能封存。成员对象初始化编译器只管父类构造不管组合成员 --不理解寓言开一家连锁酒馆看懂「继承父类构造」和「组合成员变量」的编译器区别人物设定酒馆总店 父类开分店必须先建好总店的地基、消防、执照总店的硬性规则没人能跳过分店门店 子类继承你想开一家分店属于总店体系下的门店酒馆里的调酒师 组合成员对象分店自己聘请的员工是分店单独持有的一个外部对象第一部分继承分店→总店编译器市场监管局强制先走父类构造市场监管局编译器有死规定任何一家挂靠总店的分店开业之前总店本身必须是合法完工状态。总店建造父类构造方法铺设下水、办理消防证件、搭建房屋主体这套流程是法定必填项。你修建分店的时候哪怕你完全不管总店监管系统会自动强制调用总店的施工流程隐式super()如果你故意删掉总店施工流程、或者写了错误的构造调用监管直接不给你下发开业许可代码编译报错。一句话继承是上下级从属关系上层的基础建设由法律Java语法强制兜底、强制执行不做就不让编译。第二部分组合分店→调酒师编译器只管登记姓名不管真人上岗分店内部需要一名调酒师干活你在分店图纸里写下「本店配置一名调酒师」也就是代码里写Bartender bartender;成员变量。监管局编译器只会做一件事给这个岗位默认填上“人员空缺null”。监管完全不会不会强制要求你开业前必须招聘到位、办理入职不会主动帮你去找调酒师、完成实例化new Bartender()不会校验你这家店有没有调酒师。你要是勤快开店前在图纸上直接写明招聘好人、或者开店装修构造方法时招好人营业调酒正常运行你要是偷懒只标注了岗位全程不去招人门店开张后客人点酒你喊调酒师干活当场没人在岗运行时空指针NPE崩溃。监管局的逻辑很简单总店是体系根基影响整个门店合法性必须强制校验调酒师只是门店的一个私有工具人属于门店自己的业务细节官方不插手你的人事管理出事自己负责。对应原文四条知识点一一对照继承强制递归初始化基类不写super直接报错开分店必须逐层把总店、总店的上级总部全部施工完毕super省略编译器自动补手动写错super参数直接施工审批驳回编译报错。组合成员编译器不会强制初始化默认null极易空指针只登记岗位名称默认状态就是空缺null什么时候招人完全由店家自己决定营业调用岗位功能就会出问题。成员四种初始化方式店家四种招人时机定义处初始化图纸上直接写明「本店自带调酒师张三」Bartender b new Bartender();构造器初始化门店装修施工的时候同步完成招聘实例代码块初始化门店动工阶段自动执行招人流程懒加载客人第一次点酒的时候现场临时招人上岗这四种方式全是店家自主行为监管全程不会插手兜底校验。核心本质总结继承 层级血缘根基语言层面强制安全校验组合 自己持有的外部资源语法只分配内存引用业务正确性完全交给开发者自己管控。习题巩固第1题向上转型知识点单选关于Java向上转型说法正确的是A. 向上转型后子类独有的成员方法会被销毁删除B.父类 引用 new 子类()属于向上转型编译自动通过C. 继承设计的首要目的是复用父类代码多态只是附加效果D. 向上转型调用重写方法执行的是父类里面的方法实现正确答案B解析A错误子类方法本体依旧存在只是父类引用无法直接访问没有被销毁B正确父类引用 new 子类实例就是标准向上转型Java自动隐式转换无需强制转型C错误继承核心价值是依托向上转型实现多态代码复用只是附带收益D错误向上转型执行重写方法实际运行的是子类重写后的代码。第2题GC与资源释放单选针对Java GC与系统资源释放描述正确的是A. 对象变成垃圾后GC回收内存时会自动关闭文件流、数据库连接B. finalize方法执行时机可控可用它放心关闭各类系统资源C. FileReader这类资源推荐使用try-with-resources语法自动关闭D. 调用System.gc()程序就会立刻执行垃圾回收动作正确答案C解析A错误GC只回收堆内存不会主动释放文件、连接这类系统资源会造成句柄泄漏B错误finalize()执行时间不确定甚至不会执行官方早已废弃不能用来释放资源C正确所有实现AutoCloseable的流资源使用try-with-resources代码块结束自动关闭是标准最优写法D错误System.gc()只是向JVM发起回收建议无法强制、立刻触发GC。第3题protected修饰符单选protected修饰的成员变量/方法访问权限准确描述是A. 只有本类和不同包下的子类能够访问B. 同包所有类 不同包的子类可以访问C. 只要是子类不管是否同包都能随意访问D. 仅本类内部可以访问正确答案B解析A错误漏掉了同包普通类也能访问表述不全B正确精准匹配规则同一包全部类可访问跨包仅子类有权访问C错误跨包无关类就算名称相似也无法访问D错误该描述是private的权限范围。第4题静态方法遮蔽单选执行以下代码打印结果是classParent{publicstaticvoidtest(){System.out.println(父静态);}}classSonextendsParent{publicstaticvoidtest(){System.out.println(子静态);}}ParentpnewSon();p.test();A. 父静态B. 子静态C. 编译报错D. 运行异常正确答案A解析静态方法不存在重写属于静态遮蔽。静态方法的调用绑定左侧引用类型此处引用是Parent类型和右边实际new出来的Son对象无关因此执行父类的静态方法打印「父静态」。链接《Java编程思想》重点章节踩坑学习规划