内部类,顾名思义就是一个 A 类的内部再定义一个 B 类。那么 A 类就是外部类, B 类就是内部类。
public class A {public class B{}}
内部类除了定义的位置有特殊性外,本质上与普通类没有区别,包括:
- 也拥有属性、构造、行为、初始化块、自己的内部类
- 内部类虽然和外部类书写在同一篇 .java 文件,但编译后拥有自己独立的 .class 文件
- 内部类的类名不是书写的简单名,而是和外部类的类名共同组成的
根据内部类书写的位置,可以分为两大类:
- 成员内部类
-
成员内部类
如果一个内部类是直接定在外部类的
{}里,它的位置与外部类的属性、方法、构造平行,称为“成员内部类”。它是最普通的内部类,作为外部类的成员,它也能拥有访问修饰符来控制这个内部类能否被外部使用。1. 普通成员内部类
// Outside.javapublic class Outside{// 内部类位置与外部类的属性、方法、构造器平行,所以就作为了外部类的成员内部类class Inside{}// 外部类的构造public Outside(){}// 外部类有自己的属性、方法private String name;public void print(){}}
若内部类
class Inside{}添加了 private 修饰,则表示只能在其外部类class Outside{}中使用;若添加的是 public 则表示外部类外其他类也都可以使用。
要使用普通成员内部类,要先产生外部类的对象,再用外部类对象.new 内部类()产生内部类对象:外部类型 外部实例名称 = new 外部类();外部类.内部类类型 实例名称 = 外部实例.new 内部类();
// Outside.javapublic class Outside {// 外部类属性public String nameOutside = "外部类";// 内部类public class Inside {public String nameInside = "内部类 inside";// 内部类访问外部类属性值public void print() {System.out.println(nameInside + "," + nameOutside);}}}// TestMain.javapublic class TestMain {public static void main(String[] args) {// 外部类的实例Outside outsideObj = new Outside();/*内部类作为了外部类的成员,所以创建内部类实例的语法*/Outside.Inside insideObj = outsideObj.new Inside();insideObj.print();}}
2. 静态内部类
由于添加了 static 修饰,所以该静态内部类与它所属的外部类实例对象无关,就无须产生外部对象了。直接使用外部类类名访问。
Outsize.Inside inner2 = new Outsize.Inside();
局部内部类
局部内部类也被称为方法内部类,“局部”这个词也是老熟人了,提到作用域就肯定会提到它。既然是局部 XX 也就是指它是被定义在外部类的某个函数中的,它的书写位置与该方法的局部变量平级。作为方法的内部定义,同局部变量一样,只能在函数内部使用、没有访问修饰符。
3. 局部内部类
局部内部类只能在定义它的函数里使用。 ```java // Outside.java public class Outside { // 外部类属性 public String nameOutside = “外部类”;
public void foo() {
class Inside {String nameInside = "内部类 inside";public void print() {System.out.println(nameInside + "," + nameOutside);}}new Inside().print();
} }
// TestMain.java public class TestMain { public static void main(String[] args) { // 外部类的实例 Outside outsideObj = new Outside(); outsideObj.foo(); } }
<br />对于参数的使用,也是需要小心操作的。内部类中,书写 this 代表的是当前内部类对象,若要表示它所关联的外部类,要写成 `外部类.this.属性`。局部内部类中的方法,可以操作外部类属性。```java// Outside.javapublic class Outside {// 外部类属性public String nameOutside = "外部类";public int number = 5;public void foo() {class Inside {String nameInside = "内部类 inside";public int number = 10;public void print() {System.out.println(nameInside + "," + nameOutside);}public void printNumber(int number) {System.out.println(number);System.out.println(this.number); // 访问自身属性System.out.println(Outside.this.number); // 访问外部类属性}}Inside inside = new Inside();inside.printNumber(number);}}// TestMain.javapublic class TestMain {public static void main(String[] args) {// 外部类的实例Outside outsideObj = new Outside();outsideObj.foo();}}
4. 匿名内部类
匿名内部类是在 new 对象同时去定义这个对象中的属性和行为的,由于没有取名字只能使用一次。
new Object(){private int a;public void test(){}}.test();
编译后的文件
含有内部类的 .java 文件在编译后会一个类生成一篇 .class 文件,在 out 文件夹可以查看
- 成员内部类编译后的 .class 文件名:外部类名字+$+内部类的名字
- 局部内部类编译后 .class 文件名:外部类名+$序号+内部类名
- 一个函数中可能会存在多个局部内部类,编译后序号从1开始,是同名局部内部类编译的顺序序号
根据语法特殊性,成员内部类 和 局部内部类 可被分为:
- 成员内部类分为:普通成员内部类、静态内部类
- 区别就在于加不加 static 关键字
- 局部内部类分为:普通局部内部类、匿名内部类
- 匿名内部类就是没有给类取类名的。由于没有名字就无法再次使用了,所以在定义时马上产生对象,只能使用一次

