Java内部类知识点总结
和外部类的成员变量、成员方法同级(在外部类的类体中,方法外面),相当于外部类的一个 “成员”在外部类的某个方法 / 代码块里面(比如 main 方法、普通成员方法),相当于方法里的一个 “局部变量”。和局部内部类一样,在方法 / 代码块里面,是特殊的局部内部类和成员内部类一样,在外部类的类体中,方法外面,但多了一个static 修饰符内部类是定义在类里面的类,核心优势是能直接访问外部类所有成员,且
内部类就是定义在一个类里面的类,比如类 A 里定义了类 B,那么 B 就是 A 的内部类,A 是 B 的外部类。核心作用:让内部类能直接访问外部类的所有成员(包括 private 私有),同时让内部类的代码更 “隐蔽”,和外部类形成紧密的逻辑关联,减少类的命名冲突
先记一个基础结构:

一、成员内部类
1. 定义位置
和外部类的成员变量、成员方法同级(在外部类的类体中,方法外面),相当于外部类的一个 “成员”
2. 核心特点
- 属于外部类的实例成员,依赖外部类的对象存在(没有外部类对象,就不能创建内部类对象)
- 能直接访问外部类的所有成员(包括 private、静态成员)
- 自身不能定义静态成员(static 变量 / 方法),除非是
static final常量(小白先记这个规则,不用深究原因)
3. 完整使用步骤
步骤 1:定义外部类和成员内部类
步骤 2:创建外部类对象(内部类依赖它)
步骤 3:通过外部类对象创建内部类对象,调用内部类方法
代码示例:


运行结果:

4. 必看注意事项
1.外部类要访问内部类的成员,必须创建内部类对象(和普通类调用规则一致,因为内部类是外部类的成员)
示例:在 Phone 类中加一个方法,访问 Battery 的 showInfo ()

2.内部类的访问修饰符:可以用public/protected/default/private(普通类只能用 public/default),用 private 时,只有外部类能访问内部类,更隐蔽
3.重名问题:如果内部类和外部类有同名成员,内部类中默认访问自身的,要访问外部类的同名成员,用外部类名.this.成员名:

二、局部内部类
1. 定义位置
在外部类的某个方法 / 代码块里面(比如 main 方法、普通成员方法),相当于方法里的一个 “局部变量”。
2. 核心特点
- 属于外部类方法的局部成员,只能在定义它的方法内部使用,方法外部完全访问不到
- 依赖外部类对象 + 方法调用(只有调用方法,局部内部类才会被加载)
- 能直接访问外部类的所有成员,但不能访问方法中的非 final 局部变量(JDK8 及以上自动把 “被局部内部类访问的局部变量” 视为 final,小白不用手动加,记规则即可)
- 不能加任何访问修饰符(public/protected/private),也不能加 static(因为是局部的)
3. 完整使用步骤
步骤 1:在外部类的方法中定义局部内部类,并在方法内创建内部类对象、调用方法
步骤 2:调用外部类的这个方法(间接使用局部内部类,因为外部访问不到)
代码示例:


运行结果:
![]()
4. 必看注意事项
- 局部内部类的作用域仅限定义它的方法,方法执行完,内部类就会被销毁
- 为什么不能访问非 final 局部变量?因为局部变量存在栈内存(方法执行完就没了),而内部类对象存在堆内存(生命周期更长),JDK8 的 “自动 final” 保证了变量值不会被修改,避免数据不一致
三、匿名内部类!
1. 定义位置
和局部内部类一样,在方法 / 代码块里面,是特殊的局部内部类
2. 核心特点
- 没有类名(“匿名” 的由来),不能单独定义,必须在创建对象的同时定义,一步完成
- 必须继承一个父类或实现一个接口(这是匿名内部类的唯一创建方式)
- 一次性使用:创建的对象是 “临时对象”,只能用一次(除非把对象赋值给父类 / 接口引用)
- 能直接访问外部类的所有成员,也遵循 “访问方法局部变量需 final” 的规则
- 语法简洁,开发中最常用(比如按钮点击、线程创建、接口回调)
3. 核心使用场景
当你需要快速创建一个类的对象,且这个类只使用一次,不需要单独命名时,就用匿名内部类(小白最常见的场景:实现接口、继承抽象类)
4. 核心语法
语法 1:实现接口

语法 2:继承抽象类

代码示例(实现接口):
以 “吃饭” 接口为例,快速创建实现类对象,不用单独写一个类:



运行结果:

6. 必看注意事项
- 匿名内部类没有构造器(因为没有类名),如果需要初始化,可以在方法体中直接写代码
- 匿名内部类如果要访问方法的局部变量,变量依然要遵循 “final” 规则(JDK8 自动加)
- 开发中匿名内部类常用来简化代码,比如创建线程(
new Runnable(){...})、Swing 按钮点击(button.addActionListener(new ActionListener(){...})),后续学这些知识点时会频繁用到
四、静态内部类
1. 定义位置
和成员内部类一样,在外部类的类体中,方法外面,但多了一个static 修饰符
2. 核心特点
- 属于外部类本身,不是外部类的实例成员,不依赖外部类对象(可以直接通过外部类名访问,这是和其他内部类最大的区别)
- 能直接访问外部类的静态成员(包括 private),不能直接访问外部类的非静态成员(因为静态内部类是 “静态的”,非静态成员依赖对象)
- 自身可以定义任意成员(静态、非静态都可以),和普通类几乎一样
- 相当于一个 “独立的类”,只是被定义在外部类里面,减少命名冲突
3. 完整使用步骤
步骤 1:定义外部类和静态内部类
步骤 2:创建静态内部类对象(直接用外部类名,不用外部类对象)
格式:外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();
代码示例:


运行结果:

4. 必看注意事项
- 静态内部类是最特殊的内部类,和外部类的关联最弱,几乎就是一个 “放在外部类里的普通类
- 访问规则遵循Java 静态规则:静态只能访问静态,非静态可以访问静态 + 非静态
- 静态内部类的访问修饰符:和成员内部类一样,可以用
public/protected/default/private
五、4 种内部类核心区别
| 内部类类型 | 定义位置 | 是否依赖外部类对象 | 能访问的外部类成员 | 能否定义静态成员 | 访问修饰符 |
|---|---|---|---|---|---|
| 成员内部类 | 外部类体中,方法外 | 是 | 所有(静态 + 非静态,包括 private) | 仅 static final 常量 | 全支持(4 种) |
| 局部内部类 | 外部类的方法 / 代码块中 | 是 | 所有(静态 + 非静态) | 不能 | 不能加 |
| 匿名内部类 | 外部类的方法 / 代码块中 | 是 | 所有(静态 + 非静态) | 不能 | 不能加 |
| 静态内部类 | 外部类体中,方法外 | 否 | 仅静态成员(包括 private) | 能(任意静态 / 非静态) | 全支持(4 种) |
六、内部类的通用访问规则
- 内部类访问外部类:除了静态内部类,其他都能直接访问所有成员(包括 private);静态内部类只能访问外部类的静态成员,要访问非静态必须 new 外部类对象
- 外部类访问内部类:无论哪种内部类,都必须创建内部类对象(静态内部类用
外部类名.内部类名创建,其他用外部类对象创建) - 外部其他类访问内部类:
- 成员内部类:
外部类对象.new 内部类名() - 静态内部类:
new 外部类名.内部类名() - 局部 / 匿名内部类:访问不到(只能在定义的方法内使用)
- 成员内部类:
七、内部类的使用场景
- 当一个类和另一个类逻辑紧密关联,且这个类只给外部类使用(比如手机和电池、公司和部门),用成员内部类
- 当需要在方法内创建一个临时类,且这个类只在方法内使用,用局部内部类
- 当需要快速创建一个接口 / 抽象类的对象,且这个对象只使用一次,用匿名内部类(开发中最常用,简化代码)
- 当需要在外部类里定义一个独立的类,且不想让它和外部类的对象绑定,用静态内部类(比如 Java 集合中的
ArrayList里的Itr迭代器类,就是静态内部类)
八、常见误区
- 误以为内部类可以独立创建对象:除了静态内部类,其他内部类必须先有外部类对象
- 误以为匿名内部类有类名 / 构造器:没有类名,也没有构造器,一次性使用
- 给局部 / 匿名内部类加访问修饰符:错误,这两种内部类是局部的,不能加 public/private 等
- 静态内部类直接访问外部类的非静态成员:错误,静态只能访问静态,非静态需要 new 外部类对象
总结
- 内部类是定义在类里面的类,核心优势是能直接访问外部类所有成员,且代码更隐蔽
- 4 种内部类核心区别在定义位置和是否依赖外部类对象,其中匿名内部类是开发中最常用的
- 通用规则:非静态内部类依赖对象,能访问所有成员;静态内部类不依赖对象,只能访问静态成员
- 局部 / 匿名内部类的作用域仅限定义的方法内,外部完全访问不到
更多推荐


所有评论(0)