11. Java面向对象进阶笔记

发布时间:2026/9/3 8:41:22
11. Java面向对象进阶笔记 目录一、static关键字1.1 核心概念1.2 静态变量特点1.3 调用方式1.4 静态变量 vs 成员变量1.5 使用场景二、工具类设计2.1 核心设计规范2.2 数组工具类 ArrayUtil2.3 学生工具类 StudentUtil2.4 工具类 vs JavaBean类三、static方法访问权限3.1 核心结论3.2 内存层面理解3.3 代码示例3.4 this关键字四、封装Encapsulation4.1 核心思想4.2 代码示例4.3 封装的好处五、继承Inheritance5.1 核心思想5.2 基本格式5.3 继承规则5.4 继承的好处5.5 什么时候用继承5.6 Object类六、继承中成员访问特点6.1 成员变量的访问特点6.2 成员方法的访问特点七、方法重写Override7.1 重写的定义7.2 重写规范7.3 代码示例7.4 重写的本质八、继承中构造方法的特点8.1 核心规则8.2 代码示例8.3 注意事项九、this与super对比十、多态Polymorphism10.1 什么是多态10.2 多态的核心表现形式10.3 多态的三个前提条件10.4 多态调用成员的特点10.5 多态的好处十一、引用类型转换11.1 自动类型转换向上转型11.2 强制类型转换向下转型11.3 instanceof关键字十二、包Package12.1 包的本质12.2 包名命名规则12.3 导包规则十三、final关键字13.1 final修饰的三种目标13.2 常量命名规范13.3 关键细节十四、权限修饰符14.1 权限修饰符对比14.2 核心作用十五、代码块15.1 局部代码块15.2 构造代码块15.3 静态代码块15.4 执行顺序十六、抽象类与抽象方法16.1 核心概念16.2 定义格式16.3 核心注意事项16.4 抽象类 vs 接口十七、接口Interface17.1 为什么需要接口17.2 接口的定义与使用17.3 接口成员的特点17.4 JDK8接口新增方法17.5 接口的核心意义十八、内部类18.1 什么是内部类18.2 内部类分类18.3 成员内部类18.4 静态内部类18.5 局部内部类18.6 匿名内部类重点十九、适配器设计模式19.1 适用场景19.2 核心思想19.3 代码示例二十、总结20.1 面向对象三大核心特征一、static关键字1.1 核心概念static是Java中的静态修饰符可修饰成员变量和成员方法。修饰目标名称特点成员变量静态变量类变量被该类所有对象共享成员方法静态方法类方法属于类不属于对象1.2 静态变量特点被该类所有对象共享不属于对象属于类随类加载而加载优先于对象创建存储在静态区方法区/元空间1.3 调用方式// 推荐类名调用 Student.teacherName 阿玮老师; // 不推荐对象名调用语法允许但语义易混淆 Student s1 new Student(); s1.teacherName 阿玮老师;1.4 静态变量 vs 成员变量对比项静态变量static成员变量非static归属属于类属于对象共享所有对象共享每个对象独有加载时机类加载时对象创建时调用方式类名/对象名只能对象名1.5 使用场景静态变量描述类级别的共享数据如班级老师、全局计数器静态方法工具类方法如Math.sqrt()无需创建对象即可调用二、工具类设计2.1 核心设计规范原则含义代码体现类名见名知意一眼看出类的功能ArrayUtil数组工具私有化构造方法禁止外部创建工具类实例private 类名(){}方法定义为静态直接通过类名调用public static 返回类型 方法名(参数)2.2 数组工具类 ArrayUtilpackage a01staticdemo1; public class ArrayUtil { /** * 私有构造方法防止外部实例化工具类 */ private ArrayUtil() {} /** * 将 int 数组格式化为 [元素1,元素2,...] 字符串 */ public static String printAll(int[] arr){ StringBuilder sb new StringBuilder(); sb.append([); for(int i 0; i arr.length; i){ if(i arr.length - 1){ sb.append(arr[i]).append(]); } else { sb.append(arr[i]).append(,); } } return sb.toString(); } /** * 计算 double 数组的平均值 */ public static double getAv(double[] arr){ double sum 0; for(int i 0; i arr.length; i){ sum arr[i]; } return sum / arr.length; } }2.3 学生工具类 StudentUtilpackage a01staticdemo1; import java.util.ArrayList; public class StudentUtil { private StudentUtil() {} /** * 从学生集合中获取年龄最大的学生的年龄值 */ public static int getMaxAge(ArrayListStudent list){ int maxAge list.get(0).getAge(); for (Student student : list) { if(student.getAge() maxAge){ maxAge student.getAge(); } } return maxAge; } }2.4 工具类 vs JavaBean类类型作用示例JavaBean类描述一类事物属性行为Student描述学生工具类提供通用功能不描述事物ArrayUtil操作数组测试类程序入口验证其他类功能Test包含main方法三、static方法访问权限3.1 核心结论方法类型能访问什么不能访问什么有没有this静态方法只能访问静态变量、静态方法不能访问非静态变量、非静态方法没有this非静态方法可以访问所有静态非静态无限制有this3.2 内存层面理解静态内容存在方法区元空间随类加载而加载非静态内容存在堆内存必须new出对象后才存在关键矛盾类加载时静态内容就有了但还没有任何对象3.3 代码示例public class Student { String name; // 堆内存属于对象 static String teacherName; // 方法区属于类 // 静态方法 public static void method() { // System.out.println(name); // 错误不能访问非静态变量 System.out.println(teacherName); // 正确可以访问静态变量 } // 非静态方法 public void show() { System.out.println(name); // 正确可以访问非静态变量 System.out.println(teacherName); // 正确可以访问静态变量 } }3.4 this关键字this代表当前调用方法的那个对象的地址JVM自动赋值。public void show1(Student this) { // 隐藏的this参数 System.out.println(this.name); }静态方法里没有this因为静态方法不需要对象。四、封装Encapsulation4.1 核心思想对象代表什么就得封装对应的数据并提供数据对应的行为。把对象的属性和行为打包在一个类里用访问权限修饰符隐藏内部细节只对外提供安全的访问方式4.2 代码示例public class Student { // 私有化属性 private String name; private int age; // 提供公共的getter/setter方法 public String getName() { return name; } public void setName(String name) { this.name name; } public int getAge() { return age; } public void setAge(int age) { this.age age; } // 封装行为 public void sleep() { System.out.println(name 在睡觉); } }4.3 封装的好处数据安全防止外部直接修改属性代码复用行为封装在类里所有对象都能复用易于维护内部实现修改不影响外部调用五、继承Inheritance5.1 核心思想让一个类继承另一个类从而复用父类的代码并在其基础上扩展新功能。5.2 基本格式public class 子类名 extends 父类名 { // 子类新增的属性和方法 }5.3 继承规则规则说明单继承一个子类只能继承一个父类不支持多继承避免方法冲突支持多层继承子类→父类→Object5.4 继承的好处代码复用把多个子类重复的代码抽取到父类中功能扩展子类可以在父类基础上新增自己的属性和方法便于维护修改父类代码所有子类自动生效5.5 什么时候用继承存在共性多个类有相同的属性和行为is-a关系子类是父类的一种5.6 Object类Java中每一个类都直接或间接继承于Object类因此都拥有Object的方法如toString()、equals()、hashCode()等。六、继承中成员访问特点6.1 成员变量的访问特点就近原则方法内局部变量 子类成员变量 父类成员变量class Fu { String name Fu; } class Zi extends Fu { String name Zi; public void ziShow() { String name ziShow; System.out.println(name); // 输出 ziShow System.out.println(this.name); // 输出 Zi System.out.println(super.name);// 输出 Fu } }6.2 成员方法的访问特点子类调用方法时优先在本类中查找若不存在则向上查找父类继承的方法this.方法名()优先调用子类方法super.方法名()强制调用父类的方法七、方法重写Override7.1 重写的定义当父类方法无法满足子类需求时子类可定义与父类方法声明完全一致的方法覆盖父类实现。7.2 重写规范规范说明声明一致方法名、参数列表必须与父类完全相同权限放大子类方法访问权限 ≥ 父类方法访问权限返回值类型子类返回值类型 ≤ 父类返回值类型协变返回类型注解推荐添加Override注解编译器会自动校验7.3 代码示例class Person { public void eat() { System.out.println(吃米饭吃菜); } } class Student extends Person { Override public void eat() { System.out.println(吃食堂套餐); // 子类重写实现 } }7.4 重写的本质子类重写父类方法时会覆盖父类方法在虚方法表中的位置运行时根据对象实际类型调用对应实现多态核心。八、继承中构造方法的特点8.1 核心规则先父类后子类创建子类对象时会先执行父类的构造方法子类构造方法中默认隐藏super()会自动调用父类的无参构造方法若父类没有无参构造子类必须显式调用父类有参构造super(参数列表)8.2 代码示例class Fu { public Fu() { System.out.println(父类无参构造执行); } } class Zi extends Fu { public Zi() { super(); // 隐藏的super() System.out.println(子类无参构造执行); } }8.3 注意事项构造方法不能被继承super()必须放在构造方法第一行this()和super()不能同时出现九、this与super对比关键字代表对象核心用途位置要求this当前对象访问本类成员、调用本类构造构造方法第一行super父类对象访问父类成员、调用父类构造构造方法第一行十、多态Polymorphism10.1 什么是多态同类型的对象表现出不同的行为形态。同一个方法调用在不同子类对象上会执行不同的逻辑。10.2 多态的核心表现形式// 父类类型 变量名 子类对象; Animal a1 new Dog(); Animal a2 new Cat();这种写法也叫向上转型。10.3 多态的三个前提条件有继承/实现关系有方法重写父类引用指向子类对象10.4 多态调用成员的特点成员类型编译时规则运行时规则口诀成员变量看「左边」父类看「左边」父类编译看左运行也看左成员方法看「左边」父类看「右边」子类编译看左运行看右10.5 多态的好处扩展性强新增子类无需修改原有代码代码复用用父类作为参数可以接收所有子类对象灵活性高统一接口调用不用关心具体子类类型十一、引用类型转换11.1 自动类型转换向上转型场景子类 → 父类特点自动完成安全可靠但会丢失子类特有功能Person p new Student();11.2 强制类型转换向下转型场景父类 → 子类目的恢复子类类型调用子类特有功能风险若转换类型与真实对象类型不一致会抛出ClassCastExceptionPerson p new Student(); Student s (Student) p; // 强转后可调用Student特有方法11.3 instanceof关键字用于校验对象真实类型配合向下转型保证安全。Animal a new Dog(); if (a instanceof Dog d) { d.lookHome(); // 直接使用d无需额外强转 }十二、包Package12.1 包的本质包就是文件夹用于分类管理不同功能的Java类。12.2 包名命名规则格式公司域名反写 包的作用要求全部英文小写见名知意示例com.itheima.domain12.3 导包规则场景是否需要导包说明同一个包中的类不需要直接使用类名java.lang包中的类不需要如String、System、Math等其他包中的类需要用import 全类名;导入两个包存在同名类必须用全类名避免歧义十三、final关键字13.1 final修饰的三种目标修饰目标含义核心限制方法最终方法不能被子类重写类最终类不能被子类继承变量常量只能被赋值一次13.2 常量命名规范单个单词全部大写如AGE多个单词全部大写 下划线分隔如MAX_VALUE13.3 关键细节基本类型变量存储的数据值不可改变引用类型变量存储的地址值不可改变但对象内部属性可以修改final int NUM 10; // NUM 20; // 编译报错 final Dog d new Dog(); // d new Dog(); // 编译报错 d.setAge(3); // 可以修改对象内部属性十四、权限修饰符14.1 权限修饰符对比修饰符本类同一个包不同包子类不同包无关类private✓✗✗✗默认空着不写✓✓✗✗protected✓✓✓✗public✓✓✓✓14.2 核心作用private最高封装仅类内部使用默认权限包级封装适合仅在模块内部共享的成员protected继承友好允许子类复用父类功能public对外接口提供稳定的功能入口十五、代码块15.1 局部代码块用于限制变量的作用域让变量在代码块执行结束后立即被回收。public class LocalBlockDemo { public static void main(String[] args) { { int temp 100; // 变量仅在块内有效 System.out.println(局部代码块内: temp temp); } // System.out.println(temp); // 编译报错temp已超出作用域 } }15.2 构造代码块在每次创建对象时、构造方法执行前自动调用用于抽取多个构造方法中的重复代码。public class Student { private String name; // 构造代码块 { System.out.println(构造代码块执行初始化公共资源); } public Student() { System.out.println(无参构造执行); } }15.3 静态代码块随类的第一次加载而执行且整个程序生命周期仅执行一次用于完成类级别的数据初始化。public class StaticBlockDemo { public static String config; // 静态代码块 static { System.out.println(静态代码块执行加载配置文件); config 读取自配置文件的参数; } }15.4 执行顺序静态代码块 → 类加载时执行仅一次构造代码块 → 每次创建对象时执行在构造方法前构造方法 → 完成对象的最终初始化局部代码块 → 方法执行到该块时才执行十六、抽象类与抽象方法16.1 核心概念抽象方法只有方法声明没有方法体用abstract关键字修饰。抽象类包含抽象方法的类必须被定义为抽象类。16.2 定义格式// 抽象类 public abstract class Animal { // 普通成员方法 public void drink() { System.out.println(动物喝水); } // 抽象方法 public abstract void eat(); }16.3 核心注意事项抽象类不能实例化抽象类中不一定有抽象方法但包含抽象方法的类必须是抽象类抽象类可以有构造方法子类继承抽象类必须重写所有抽象方法或者也声明为抽象类16.4 抽象类 vs 接口维度抽象类接口继承/实现关系类用extends继承单继承类用implements实现多实现构造方法有构造方法无构造方法成员变量可以有普通成员变量只能有public static final常量方法类型可包含抽象方法、普通方法等可包含抽象方法、默认方法、静态方法十七、接口Interface17.1 为什么需要接口抽象类是单继承且父类的行为会强制所有子类继承。接口将非体系共性、可插拔的行为抽成接口作为一种规则打破单继承限制。17.2 接口的定义与使用// 定义接口 public interface Swimable { void swim(); // 抽象方法 } // 类实现接口 public class Frog extends Animal implements Swimable { Override public void swim() { System.out.println(青蛙在水里游); } } // 多实现 public class Student extends Person implements Swimable, Runnable { Override public void swim() { ... } Override public void run() { ... } }17.3 接口成员的特点成员类型特点成员变量默认public static final必须初始化本质是常量抽象方法默认public abstract可省略修饰符默认方法Java 8用default修饰有方法体静态方法Java 8用static修饰有方法体17.4 JDK8接口新增方法JDK版本新增方法类型修饰关键字调用方式JDK8默认方法default实现类对象调用JDK8静态方法static接口名调用JDK9私有方法private仅接口内部调用17.5 接口的核心意义解耦将行为与类的继承体系分离规范定义统一的行为规则多实现打破单继承局限跨体系接口可以被任意体系的类实现十八、内部类18.1 什么是内部类在一个类的内部再定义一个完整的类这个被嵌套在内部的类就叫做内部类。适用场景当一个类B表示的事物是另一个类A的组成部分且B类单独存在没有任何意义时。18.2 内部类分类内部类类型定义位置学习要求成员内部类外部类成员位置了解静态内部类外部类成员位置static修饰了解局部内部类外部类的方法/代码块内部了解匿名内部类方法/代码块内部无类名掌握重点18.3 成员内部类定义在外部类的成员位置属于外部类的成员。public class Car { String carName; // 成员内部类 class Engine { String engineName; } }创建对象格式Car.Engine engine new Car().new Engine();18.4 静态内部类用static修饰的内部类属于外部类的静态成员不依赖外部类对象。public class Car { public static String brand BMW; static class Engine { public void show() { System.out.println(品牌 brand); } } }创建对象格式Car.Engine engine new Car.Engine();18.5 局部内部类定义在外部类的方法/代码块内部作用域仅限于当前方法/代码块。public class Outer { public void show() { int a 10; // JDK8 要求effectively final class Inner { public void method1() { System.out.println(a); } } Inner inner new Inner(); inner.method1(); } }18.6 匿名内部类重点本质上是一个没有名字的局部内部类适用于某个类/接口只需要使用一次的场景。标准格式new 类名/接口名() { // 重写方法 Override public 返回值 方法名(参数) { // 方法实现 } };代码示例interface Swim { void swim(); } public class Test { public static void main(String[] args) { // 匿名内部类实现Swim接口 Swim s new Swim() { Override public void swim() { System.out.println(重写之后游泳方法); } }; s.swim(); } }核心规则访问权限可直接访问外部类的所有成员包括private不能有构造器因为没有类名单继承/单实现限制只能继承一个类或实现一个接口分号问题匿名内部类的大括号}后面必须加分号;十九、适配器设计模式19.1 适用场景当一个接口包含大量抽象方法但实现类只需要使用其中部分方法时通过适配器模式简化实现。19.2 核心思想用一个抽象适配器类实现接口对所有抽象方法做空实现再让业务实现类继承适配器类仅重写需要的方法。19.3 代码示例// 原接口 interface 原接口 { void 方法1(); void 方法2(); void 方法3(); } // 适配器类 abstract class XXXAdapter implements 原接口 { Override public void 方法1() {} Override public void 方法2() {} Override public void 方法3() {} } // 业务实现类 class 业务类 extends XXXAdapter { Override public void 方法1() { // 只重写需要的方法 } }二十、总结20.1 面向对象三大核心特征特征核心思想实现手段封装隐藏内部细节只暴露必要接口private getter/setter继承复用代码并扩展功能extends多态同一行为在不同子类上表现不同父类引用指向子类对象