目录

一、static关键字

1.1 核心概念

1.2 静态变量特点

1.3 调用方式

1.4 静态变量 vs 成员变量

1.5 使用场景

二、工具类设计

2.1 核心设计规范

2.2 数组工具类 ArrayUtil

2.3 学生工具类 StudentUtil

2.4 工具类 vs JavaBean类

三、static方法访问权限

3.1 核心结论

3.2 内存层面理解

3.3 代码示例

3.4 this关键字

四、封装(Encapsulation)

4.1 核心思想

4.2 代码示例

4.3 封装的好处

五、继承(Inheritance)

5.1 核心思想

5.2 基本格式

5.3 继承规则

5.4 继承的好处

5.5 什么时候用继承

5.6 Object类

六、继承中成员访问特点

6.1 成员变量的访问特点

6.2 成员方法的访问特点

七、方法重写(Override)

7.1 重写的定义

7.2 重写规范

7.3 代码示例

7.4 重写的本质

八、继承中构造方法的特点

8.1 核心规则

8.2 代码示例

8.3 注意事项

九、this与super对比

十、多态(Polymorphism)

10.1 什么是多态

10.2 多态的核心表现形式

10.3 多态的三个前提条件

10.4 多态调用成员的特点

10.5 多态的好处

十一、引用类型转换

11.1 自动类型转换(向上转型)

11.2 强制类型转换(向下转型)

11.3 instanceof关键字

十二、包(Package)

12.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 接口

十七、接口(Interface)

17.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 数组工具类 ArrayUtil

package 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 学生工具类 StudentUtil

package a01staticdemo1;

import java.util.ArrayList;

public class StudentUtil {
    private StudentUtil() {}

    /**
     * 从学生集合中获取年龄最大的学生的年龄值
     */
    public static int getMaxAge(ArrayList<Student> 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
非静态方法 可以访问所有(静态+非静态) 无限制 有this

3.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,因为静态方法不需要对象。


四、封装(Encapsulation)

4.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 封装的好处

  • 数据安全:防止外部直接修改属性
  • 代码复用:行为封装在类里,所有对象都能复用
  • 易于维护:内部实现修改不影响外部调用

五、继承(Inheritance)

5.1 核心思想

让一个类继承另一个类,从而复用父类的代码,并在其基础上扩展新功能。

5.2 基本格式

public class 子类名 extends 父类名 {
    // 子类新增的属性和方法
}

5.3 继承规则

规则 说明
单继承 一个子类只能继承一个父类
不支持多继承 避免方法冲突
支持多层继承 子类→父类→Object

5.4 继承的好处

  1. 代码复用:把多个子类重复的代码抽取到父类中
  2. 功能扩展:子类可以在父类基础上,新增自己的属性和方法
  3. 便于维护:修改父类代码,所有子类自动生效

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.方法名():强制调用父类的方法

七、方法重写(Override)

7.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 父类对象 访问父类成员、调用父类构造 构造方法第一行

十、多态(Polymorphism)

10.1 什么是多态

同类型的对象,表现出不同的行为形态。同一个方法调用,在不同子类对象上,会执行不同的逻辑。

10.2 多态的核心表现形式

// 父类类型 变量名 = 子类对象;
Animal a1 = new Dog();
Animal a2 = new Cat();

这种写法也叫向上转型

10.3 多态的三个前提条件

  1. 有继承/实现关系
  2. 有方法重写
  3. 父类引用指向子类对象

10.4 多态调用成员的特点

成员类型 编译时规则 运行时规则 口诀
成员变量 看「左边」(父类) 看「左边」(父类) 编译看左,运行也看左
成员方法 看「左边」(父类) 看「右边」(子类) 编译看左,运行看右

10.5 多态的好处

  • 扩展性强:新增子类无需修改原有代码
  • 代码复用:用父类作为参数,可以接收所有子类对象
  • 灵活性高:统一接口调用,不用关心具体子类类型

十一、引用类型转换

11.1 自动类型转换(向上转型)

  • 场景:子类 → 父类
  • 特点:自动完成,安全可靠,但会丢失子类特有功能
Person p = new Student();

11.2 强制类型转换(向下转型)

  • 场景:父类 → 子类
  • 目的:恢复子类类型,调用子类特有功能
  • 风险:若转换类型与真实对象类型不一致,会抛出ClassCastException
Person p = new Student();
Student s = (Student) p; // 强转后可调用Student特有方法

11.3 instanceof关键字

用于校验对象真实类型,配合向下转型保证安全。

Animal a = new Dog();
if (a instanceof Dog d) {
    d.lookHome(); // 直接使用d,无需额外强转
}

十二、包(Package)

12.1 包的本质

包就是文件夹,用于分类管理不同功能的Java类。

12.2 包名命名规则

  • 格式:公司域名反写 + 包的作用
  • 要求:全部英文小写,见名知意
  • 示例:com.itheima.domain

12.3 导包规则

场景 是否需要导包 说明
同一个包中的类 不需要 直接使用类名
java.lang包中的类 不需要 如String、System、Math等
其他包中的类 需要 用import 全类名;导入
两个包存在同名类 必须用全类名 避免歧义

十三、final关键字

13.1 final修饰的三种目标

修饰目标 含义 核心限制
方法 最终方法 不能被子类重写
最终类 不能被子类继承
变量 常量 只能被赋值一次

13.2 常量命名规范

  • 单个单词:全部大写,如AGE
  • 多个单词:全部大写 + 下划线分隔,如MAX_VALUE

13.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 执行顺序

  1. 静态代码块 → 类加载时执行(仅一次)
  2. 构造代码块 → 每次创建对象时执行(在构造方法前)
  3. 构造方法 → 完成对象的最终初始化
  4. 局部代码块 → 方法执行到该块时才执行

十六、抽象类与抽象方法

16.1 核心概念

抽象方法:只有方法声明,没有方法体,用abstract关键字修饰。

抽象类:包含抽象方法的类必须被定义为抽象类。

16.2 定义格式

// 抽象类
public abstract class Animal {
    // 普通成员方法
    public void drink() {
        System.out.println("动物喝水");
    }

    // 抽象方法
    public abstract void eat();
}

16.3 核心注意事项

  1. 抽象类不能实例化
  2. 抽象类中不一定有抽象方法,但包含抽象方法的类必须是抽象类
  3. 抽象类可以有构造方法
  4. 子类继承抽象类必须重写所有抽象方法,或者也声明为抽象类

16.4 抽象类 vs 接口

维度 抽象类 接口
继承/实现关系 类用extends继承,单继承 类用implements实现,多实现
构造方法 有构造方法 无构造方法
成员变量 可以有普通成员变量 只能有public static final常量
方法类型 可包含抽象方法、普通方法等 可包含抽象方法、默认方法、静态方法

十七、接口(Interface)

17.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 接口的核心意义

  1. 解耦:将行为与类的继承体系分离
  2. 规范:定义统一的行为规则
  3. 多实现:打破单继承局限
  4. 跨体系:接口可以被任意体系的类实现

十八、内部类

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();
    }
}

核心规则

  1. 访问权限:可直接访问外部类的所有成员(包括private)
  2. 不能有构造器:因为没有类名
  3. 单继承/单实现限制:只能继承一个类或实现一个接口
  4. 分号问题:匿名内部类的大括号}后面必须加分号;

十九、适配器设计模式

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
多态 同一行为在不同子类上表现不同 父类引用指向子类对象

更多推荐