ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] >[success] # 内部类 当**一个类的定义**出现在**另外一个类的类体**中时,那么这个类叫做**内部类(Inner)**,而这个内部类**所在的类**叫做**外部类(Outer)** **内部类**和其他类中可声明使用的内容都一样,只是作为一种`类形式的成员变量`,类中的内容(**成员变量、成员方法、构造方法、静态成员、构造块和静态代码块、内部类**) >[info] ## 内部类作用 **当一个类**存在的价值**仅仅是为某一个类单独服务**时,那么就可以将这个类定义为所服务类中的内部类,这样可以**隐藏该类的实现细节**并且可以方便的访问外部类的私有成员而**不再需要提供公有的get和set方法** >[info] ## 内部类种类 1. **普通内部类** \- 直接将一个类的定义放在另外一个类的类体中。 2. **静态内部类** \- 使用static关键字修饰的内部类,隶属于类层级。 3. **局部内部类** \- 直接将一个类的定义放在方法体的内部时。 4. **匿名内部类** \- 就是指没有名字的内部类 >[warning] ### 普通(成员)内部类 * 写法格式 ~~~ `访问修饰符` class `外部类的类名` { `访问修饰符` class `内部类的类名` { 内部类的类体; } } ~~~ * 调用内部类 1. 如果**内部类是public 修饰的成员** 先创建外部类 2. 声明的内部类类型 **`外部类.内部类` 变量名 = `外部类声明对象.new` `内部类()`** 例如下面案例 ~~~ // 创建外部类 Outer outer = new Outer(); // 执行内部类 Outer.Inner inner = outer.new Inner(); // 调用 内部类show 方法 inner.show(); ~~~ >[danger] ##### 代码 ~~~ package task10; /** * 实现普通内部类 * */ public class Outer { public int num = 1; // 定义内部类 public class Inner{ // 定义内部变量 public int innerNum = 10; // 内部类构造方法 public Inner(){ System.out.println("执行内部构造方法"); } public void show(){ // 打印外部变量 System.out.println("外部num变量:"+num); // 1 System.out.println("内部变量innerNum:" + innerNum); // 10 } } } ~~~ * 调用 ~~~ public class ExecuteOuter { // 执行入口 public static void main(String[] args){ // 创建外部类 Outer outer = new Outer(); // 执行内部类 Outer.Inner inner = outer.new Inner(); // 调用 内部类show 方法 inner.show(); } } ~~~ >[danger] ##### 使用特点 1. 普通内部类和普通类一样可以定义**成员变量、成员方法以及构造方法等** 2. 普通内部类和普通类一样可以使用**final或者abstract关键字修饰**也可以使用**private或protected**关键字进行修饰。 ~~~ /*private*/public /*final*/ class Inner{ } ~~~ 3. 普通内部类需要使用**外部类对象来创建对象**。 ~~~ // 创建外部类 Outer outer = new Outer(); // 执行内部类 Outer.Inner inner = outer.new Inner(); // 调用 内部类show 方法 inner.show(); ~~~ 4. 如果内部类访问外部类中与本类内部同名的成员变量或方法时,需要使用**this关键字**。作用域就近原则,此时最近的是函数的形参,在其次this表示当前内部类,想用外部类需要 `外部类.this.变量` 调用 ~~~ /** * 实现普通内部类 * */ public class Outer { public int num = 1; // 定义内部类 /*private*/public /*final*/ class Inner{ // 定义内部变量 public int innerNum = 10; public int num = 2; // 内部类构造方法 public Inner(){ System.out.println("执行内部构造方法"); } public void show(int num){ // 打印外部变量 System.out.println("此时接受是调用传进来的num:"+num); // 此时接受是调用传进来的num System.out.println("内部类中num:" + this.num); // 2 System.out.println("外部类中的num:" + Outer.this.num); // 1 } } } ~~~ **注**:简单说(他就是一个写在类里的类,用法特性和类都一样)。 >[warning] ### 静态内部类 * 写法格式 ~~~ `访问修饰符` class `外部类的类名` { ` 访问修饰符 static` class `内部类的类名` { 内部类的类体; } } ~~~ * 调用静态内部类 ~~~ 外部类.内部类 对象名 = new 外部类.内部类(); ~~~ >[danger] ##### 使用特点 1. 静态内部类不能直接访问外部类的非静态成员。 2. 静态内部类在使用时候可以直接创建对象。例如: OuterStatic.InnerStatic innerStatic = new OuterStatic.InnerStatic(); 3. 如果静态内部类访问外部类中与本类内同名的成员变量或方法时,需要**使用类名.的方式访问**。 >[danger] ##### 代码 ~~~ public class OuterStatic { public int a = 1; public static int b = 2; public int c = 999; public static int d = 1000; // 创建静态内部类 public static class InnerStatic { // 内部类属性 public int a = 3; public static int b = 4; public void show() { // System.out.println(c); // error: 静态内部不能直接外部类的非静态成员 System.out.println(d); // 访问外部类静态属性 1000 System.out.println(a + "----" + b); // 就近原则访问内部 3----4 // 如果静态内部类访问外部类中与本类内同名的成员变量或方法时,需要使用类名.的方式访问 System.out.println(OuterStatic.b); // 2 } } } ~~~ * 调用 ~~~ public class TestOuterStatic { public static void main(String[] args) { OuterStatic.InnerStatic innerStatic = new OuterStatic.InnerStatic(); innerStatic.show(); } } ~~~ >[warning] ### 局部内部类 * 注:局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。 ~~~ 访问修饰符 class 外部类的类名 { 访问修饰符 返回值类型 成员方法名(形参列表) { (这里没有修饰符)class 内部类的类名 { 内部类的类体; } } } ~~~ * 使用局部内部类只在当前方法中有效 >[danger] ##### 特点 1. 局部内部类只能在该方法的内部可以使用。 2. 局部内部类可以在方法体内部直接创建对象。 3. 局部内部类不能使用访问控制符和static关键字修饰符。 4. 局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局部变量的声明周期不同所致。如下图虽然局部变量在局部类中使用时候会默认加上final,但如果赋值此时不符合final 定义变量,局部类中会报错 ![](https://img.kancloud.cn/4d/53/4d530b95d053cb4b1c79ef91b4b30933_764x358.png) 5. 如果方法中的成员与外部类中的成员同名,则可以使用 .this. 的形式访问外部类中的成员。 >[danger] ##### 案例 ~~~ import java.security.PublicKey; public class FunInner { // 外部类变量 int a = 1; int b = 2; public void show() { // 局部变量 int d = 3; // 如果局部 内部局部类使用该属性默认会加上final 即final int d = 3,如果只局部类使用最好加final 修饰 // 定义局部内部类,局部内部类不能使用访问控制符和static关键字修饰符 class FInner { // static int b = 2; // 内部不能不能定义 static 成员 int a = 11; int c = 4; public void show() { System.out.println(a + "---" + b + "----" + c); // 就近原则 11---2----4 System.out.println(FunInner.this.a); // 访问外部同名 1 System.out.println(d); // 访问局部 3 // d = 36; // error在局部内部类中只可以访问当前方法中 final 类型的参数与变量,final 变量不能重新赋值 } } FInner fInner = new FInner(); fInner.show(); } public static void main(String[] args) { FunInner funInner = new FunInner(); funInner.show(); } } ~~~