一、内部类概述1. 什么是内部类把一个类定义在另一个类的里面里面的类叫内部类外面的类叫外部类。 Java 内部类一共 4 种成员内部类局部内部类静态内部类静态成员内部类匿名内部类核心特点内部类可以直接访问外部类所有成员包括私有成员外部类访问内部类成员需要先创建内部类对象。二、成员内部类1. 定义位置写在外部类的成员位置和成员变量、成员方法同级不在方法里面。class Outer{ //外部类 // 成员变量 private String name 外部类私有属性; // 成员内部类 class Inner{ public void show(){ // ✅内部类可以直接访问外部类的私有成员 System.out.println(name); } } }2. 创建成员内部类对象语法外部类.内部类 对象名 new 外部类().new 内部类();完整演示代码class Outer{ private String name 外部类私有属性; //成员内部类 class Inner{ public void show(){ System.out.println(name); } } } public class Test{ public static void main(String[] args) { // 创建成员内部类对象 Outer.Inner inner new Outer().new Inner(); inner.show(); //输出外部类私有属性 } }3. 重点重名变量访问外部类.this当内部类成员变量、外部类成员变量重名时this.变量访问内部类自己的成员外部类名.this.变量访问外部类成员class Outer{ String num 外部类; class Inner{ String num 内部类; public void test(){ String num 局部变量; System.out.println(num); //局部变量 System.out.println(this.num); //内部类成员 System.out.println(Outer.this.num); //外部类成员 } } }4. 成员内部类注意事项不能定义static 静态成员static 属于类成员内部类依赖外部对象成员内部类属于外部类实例必须先有外部类对象才能创建内部类对象可以使用private修饰私有化之后外部无法直接创建内部类对象只能在外部类内部提供方法获取。class Outer{ private class Inner{ //私有成员内部类 public void show(){ System.out.println(私有内部类); } } //外部类提供方法返回内部类对象 public Inner getInner(){ return new Inner(); } }三、局部内部类1. 定义位置定义在外部类的方法里面属于方法局部。作用域只能在当前方法内使用方法外面不可见。class Outer{ public void method(){ //局部内部类写在方法内部 class Inner{ public void show(){ System.out.println(局部内部类方法); } } // 只能在当前方法内创建对象使用 Inner inner new Inner(); inner.show(); } } public class Test{ public static void main(String[] args) { Outer outer new Outer(); outer.method(); } }2. 核心特性作用域仅限于当前方法外部完全无法访问JDK8 之前访问方法的局部变量变量必须加final JDK8 及以后有效 final变量不重新赋值就可以直接访问原因局部变量在栈内存方法执行完会销毁局部内部类对象在堆生命周期更长为防止数据不一致要求变量不可修改。class Outer{ public void method(){ int num 10; //有效final没有二次赋值 class Inner{ public void show(){ System.out.println(num); //可以访问 } } Inner inner new Inner(); inner.show(); // num 20; 如果写这句上面代码直接报错 } }不能加访问修饰符public/private/protected和局部变量一样。四、静态内部类静态成员内部类1. 定义成员内部类前面加static就是静态内部类。static 属于外部类本身不依赖外部类对象。class Outer{ private static String name 外部类静态属性; //静态内部类 static class Inner{ public void show(){ //静态内部类只能直接访问外部类static成员 System.out.println(name); } } }2. 创建对象语法外部类.内部类 对象名 new 外部类.内部类();完整示例class Outer{ private static String staticStr 外部静态变量; private String instanceStr 外部实例变量; static class Inner{ public void show(){ System.out.println(staticStr); // System.out.println(instanceStr); 报错静态内部类不能直接访问外部非static成员 // 如果要访问外部实例成员必须手动创建外部类对象 Outer outer new Outer(); System.out.println(outer.instanceStr); } } } public class Test{ public static void main(String[] args) { //静态内部类创建不需要外部类对象 Outer.Inner inner new Outer.Inner(); inner.show(); } }3. 重点总结静态内部类只能直接访问外部类静态成员访问外部非静态成员需要手动 new 外部类对象创建静态内部类对象不需要外部类实例静态内部类里面可以定义静态成员。开发常用场景工具类、实体类的嵌套比如 HashMap 里面的 Node 就是静态内部类五、匿名内部类1. 定义没有名字的内部类用来简化代码一次性使用只创建一次对象。 前提必须继承一个类 / 实现一个接口。 语法格式new 接口/父类(){ //重写抽象方法 Override public void 方法名(){ } };2. 代码演示//定义接口 interface Animal{ void eat(); } public class Test{ public static void main(String[] args) { //匿名内部类相当于创建了一个没有名字的类实现Animal接口并直接new对象 Animal cat new Animal(){ Override public void eat() { System.out.println(小猫吃鱼); } }; cat.eat(); } }3. 本质匿名内部类 定义类 实现 / 继承 创建对象一步完成。这个类没有名字只能使用一次不能重复 new。4. 匿名内部类特点没有类名不能写构造方法适合接口只有少量抽象方法临时使用JDK8 之后很多场景可以用 Lambda 表达式替代可以访问外部变量同样遵守有效 final规则。5. 匿名内部类传参写法interface Run{ void run(); } class Test{ public static void test(Run r){ r.run(); } public static void main(String[] args) { //直接把匿名内部类传入方法 test(new Run(){ Override public void run() { System.out.println(奔跑); } }); } }六、四种内部类对比总表表格类型定义位置创建对象访问外部成员成员内部类外部类成员位置方法外new Outer().new Inner()可以访问所有成员包括私有不能定义 static局部内部类外部类方法内部方法内 new Inner ()访问方法局部变量要求有效 final仅方法内可用静态内部类外部类成员位置加 staticnew Outer.Inner()只能直接访问外部 static 成员匿名内部类方法中new 的时候定义直接 new无类名一次性使用实现接口 / 继承类七、高频易错点成员内部类不能写 static 成员静态内部类可以静态内部类不等于成员内部类不需要外部实例局部内部类不能加 public/private 修饰匿名内部类不是 LambdaLambda 只能用于函数式接口。