第八章 面向对象编程(高级部分)
8.1 类变量和类方法static 关键字一、类变量静态变量定义使用static修饰的成员变量属于类本身被该类所有对象共享。核心特性类加载时生成生命周期随类加载开始、随类消亡结束所有实例对象共享同一个类变量支持类名直接访问推荐也可通过对象访问。classChild{// 类变量所有Child对象共享publicstaticintcount0;privateStringname;publicChild(Stringname){this.namename;}publicvoidjoin(){System.out.println(name加入了游戏);}}publicclassChildGame{publicstaticvoidmain(String[]args){Childchild1newChild(白骨精);child1.join();Child.count;// 类名直接访问Childchild2newChild(狐狸精);child2.join();Child.count;System.out.println(一共有Child.count个小孩在玩);}}二、类方法静态方法定义使用static修饰的方法属于类本身可通过类名直接调用。核心规则不能使用this、super关键字只能访问静态成员静态变量静态方法普通成员方法可访问静态非静态所有成员常用于工具类、工厂方法。classStudent{privateStringname;privatestaticdoublefee0;// 静态变量publicStudent(Stringname){this.namename;}// 普通方法可访问静态成员publicvoidpayFee(doublefee){Student.feefee;}// 静态方法只能访问静态成员publicstaticvoidshowFee(){System.out.println(总学费Student.fee);}}publicclassStaticMethod{publicstaticvoidmain(String[]args){StudenttomnewStudent(tom);tom.payFee(100);Student.showFee();// 类名直接调用}}8.2 main 方法深度解析main()是 JVM 调用的程序入口无需创建对象即可执行静态方法不能直接访问非静态成员需先创建对象再访问支持命令行参数传递java 执行程序 参数1 参数2。publicclassMain{privatestaticStringnameabc;// 静态变量privateintn11000;// 非静态变量publicstaticvoidhi(){System.out.println(hi);}publicstaticvoidmain(String[]args){System.out.println(name);// 合法访问静态成员hi();// 合法调用静态方法// System.out.println(n1); 错误静态方法不能访问非静态成员System.out.println(newMain().n1);// 正确创建对象后访问}}8.3 代码块代码块是类的成员之一用于初始化分为普通代码块和静态代码块。一、静态代码块语法static { ... }执行时机类加载时执行且只执行一次作用初始化类的静态成员。二、普通代码块语法{ ... }执行时机创建对象时执行每创建一个对象执行一次作用初始化对象成员是构造器的补充。三、类加载时机触发静态代码块创建对象实例new创建子类对象父类会被加载访问类的静态成员静态变量/静态方法。四、创建对象的执行顺序核心先加载 → 后构造静态代码块 静态属性初始化同级按代码顺序普通代码块 普通属性初始化构造方法。五、继承关系下的执行顺序父类静态代码块 → 子类静态代码块父类普通代码块 → 父类构造器子类普通代码块 → 子类构造器。classA{static{System.out.println(A 静态代码块);}{System.out.println(A 普通代码块);}publicA(inta){System.out.println(A 构造器);}}classBextendsA{static{System.out.println(B 静态代码块);}{System.out.println(B 普通代码块);}publicB(inta,intb){super(a);System.out.println(B 构造器);}}// 执行结果A静态 → B静态 → A普通 → A构造 → B普通 → B构造六、使用细节静态代码块只能调用静态成员普通代码块可调用静态非静态成员构造器默认隐藏逻辑super()→ 执行普通代码块 → 自身逻辑。8.4 单例设计模式定义保证一个类在系统中只有一个实例并提供一个全局访问点。一、饿汉式特点类加载时就创建对象线程安全但可能造成资源浪费实现步骤构造器私有化 → 内部创建静态对象 → 提供公共静态方法获取实例。classGirlFriend{privateStringname;// 类加载时创建唯一实例privatestaticGirlFriendgfnewGirlFriend(yy);// 构造器私有化禁止外部newprivateGirlFriend(Stringname){this.namename;}// 公共静态方法获取唯一实例publicstaticGirlFriendgetInstance(){returngf;}}publicclassSingleTon01{publicstaticvoidmain(String[]args){GirlFriendgf1GirlFriend.getInstance();GirlFriendgf2GirlFriend.getInstance();System.out.println(gf1gf2);// true同一个对象}}二、懒汉式特点使用时才创建对象节省资源但多线程下存在安全问题实现步骤构造器私有化 → 定义静态引用初始为null → 方法中判断创建。classCat{privateStringname;privatestaticCatcatnull;privateCat(Stringname){this.namename;}publicstaticCatgetInstance(){// 首次调用才创建对象if(catnull){catnewCat(yy);}returncat;}}8.5 final 关键字常量final表示最终、不可修改可修饰类、方法、变量。一、核心作用修饰类类不能被继承如 String、包装类修饰方法方法不能被子类重写修饰变量变为常量只能赋值一次不可修改。二、赋值规则普通 final 属性赋值位置 → 定义时、构造器、普通代码块静态 final 属性赋值位置 → 定义时、静态代码块不能在构造器赋值。三、重要细节final 常量命名大写字母下划线如MAX_VALUEfinal 不能修饰构造器static final搭配使用编译器优化类不会被加载效率更高包装类Integer、Double等、String 都是 final 类。finalclassA{// 静态常量publicstaticfinalintMAX_NUM100;// 成员常量publicfinaldoubleTAX_RATE0.08;// final方法不能重写publicfinalvoidhi(){System.out.println(hi);}}8.6 抽象类一、定义使用abstract修饰的类不能实例化可包含抽象方法普通方法。二、核心特性不能用new创建对象可包含抽象方法无方法体、普通方法、属性、构造器构造器用于子类初始化super()子类继承抽象类必须实现所有抽象方法否则子类也要声明为 abstract抽象方法不能用private、final、static修饰。三、模板设计模式经典应用抽象类定义固定流程子类实现具体逻辑提高代码复用性。// 抽象模板类abstractclassTemplate{// 抽象方法子类实现abstractpublicvoidjob();// 模板方法固定流程publicvoidcalTime(){longstartSystem.currentTimeMillis();job();// 动态绑定longendSystem.currentTimeMillis();System.out.println(耗时(end-start));}}// 子类实现具体逻辑classAextendsTemplate{Overridepublicvoidjob(){for(longi0;i10000000;i);}}8.7 接口一、定义接口是行为规范只定义方法声明不实现方法用interface定义。二、语法interface接口名{// 属性默认 public static final// 方法抽象方法默认public abstract、default方法、static方法}class类名implements接口{// 必须实现所有抽象方法}三、核心规则接口不能实例化接口属性默认public static final常量通过接口名直接访问接口方法默认public abstract一个类可实现多个接口弥补单继承局限性接口可继承多个接口抽象类实现接口可不用实现抽象方法。四、接口 vs 继承继承is-a关系解决代码复用和扩展接口like-a关系解决行为规范更灵活开发原则继承接口搭配使用。// 父类classMonkey{publicvoidclimbing(){System.out.println(会爬树);}}// 接口行为扩展interfaceFishable{voidswimming();}interfaceBirdable{voidfly();}// 子类继承实现接口classLittleMonkeyextendsMonkeyimplementsFishable,Birdable{Overridepublicvoidswimming(){System.out.println(会游泳);}Overridepublicvoidfly(){System.out.println(会飞翔);}}五、接口多态多态参数接口类型可接收任意实现类对象多态数组接口数组可存放不同实现类对象多态传递接口继承后实现类自动实现所有父接口。8.8 内部类一、定义一个类嵌套在另一个类内部称为内部类可直接访问外部类私有成员体现包含关系。类的五大成员属性、方法、构造器、代码块、内部类。二、分类及使用1. 局部内部类定义在方法/代码块中作用域仅在当前方法/代码块内有效不能使用访问修饰符可加final访问外部类成员外部类名.this.成员解决重名问题。2. 匿名内部类重点无类名本质类 对象一次性使用简化代码语法new 类/接口() { 实现方法 }最佳实践作为实参直接传递。// 接口interfaceBell{voidring();}classCellphone{// 接收接口类型参数publicvoidalarmclock(Bellbell){bell.ring();}}publicclassTest{publicstaticvoidmain(String[]args){CellphonephonenewCellphone();// 匿名内部类作为实参直接实现接口phone.alarmclock(newBell(){Overridepublicvoidring(){System.out.println(懒猪起床了);}});}}3. 成员内部类定义在类中无static属于外部类对象可访问外部类所有成员外部使用外部类对象.new 内部类()。4. 静态内部类定义在类中有static属于外部类本身只能访问外部类静态成员外部使用new 外部类.内部类()。三、内部类核心总结匿名内部类是开发面试重点常用于简化接口实现成员/静态内部类属于外部类成员局部/匿名内部类属于方法局部内部类可直接访问外部类私有成员外部类需创建对象访问内部类。全文总结本文覆盖 Java 面向对象进阶7大核心模块static类变量/方法共享资源静态只能访问静态代码块静态类加载一次、普通对象创建执行执行顺序固定单例饿汉式安全浪费、懒汉式省资源线程不安全final不可修改修饰类/方法/变量抽象类模板模式不能实例化定义规范接口行为规范多实现弥补单继承内部类直接访问外部私有成员匿名内部类重点掌握。