目录
定义:一个类的内部完整的嵌套了另一个类结构,被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。
内部类是类的五大成员(属性、方法、构造器、代码块、内部类)之一。
特点:内部类最大的特点就是可以直接访问外部类的所有属性、方法,包括私有的,并且可以体现类与类之间的包含关系。
注意点:内部类内部不允许使用static修饰属性、方法,也就是不允许定义静态属性、静态方法。
- //外部类
- public class OuterClass {
- //内部类
- public class innerClass{
-
- }
- }
- //外部其他类
- class OuterOtherClass{
-
- }
编译器编译时,会编译成3个字节码文件,内部类的字节码文件名称是(外部类名$内部类名)。
若是局部内部类,则生成外部类名$正整数+内部类名;
若是匿名内部类,则生成外部类名$正整数。
额外知识点:一个java文件可以定义多个外部类,外部类不写修饰符,默认是default权限。
若使用public修饰符修饰外部类,则只能有一个外部类可以使用public修饰符修饰,且java文件名称必须与public修饰的外部类相同。
为什么内部类可直接访问外部类对象的任意成员,可参考Java内部类详解 - Matrix海子 - 博客园的第二章深入理解内部类。
- //外部类
- public class OuterClass {
- private int num = 2;
-
- public void test(){
- System.out.println("外部类成员方法");
- }
-
- //成员内部类
- public class InnerClass{
- private int num = 1;
-
- public void printNum(){
- //访问外部类成员,直接访问
- test();
- //若与外部类成员重名,遵循就近原则,默认访问成员内部类的成员
- System.out.println(num);
- //访问外部类重名成员,通过外部类名.this.成员访问
- System.out.println(OuterClass.this.num);
- }
- }
- }
反编译成员内部类的class文件,也就是OuterClass$InnerClass.class文件。
可发现,内部类在构造器方法上默认添加了一个外部类类型的参数。创建内部类对象时,将外部类对象当作形参传进来,然后赋值给内部类对象的this$0(this$0是编译器会自动为成员内部类生成的外部类类型的属性),可通过this$0来访问外部类对象,所以成员内部类才可任意访问外部类的成员。

- //外部类
- public class OuterClass {
- private int num = 2;
- //成员属性:创建内部类对象
- private InnerClass innerClass = new InnerClass();
-
- //成员内部类
- public class InnerClass{
- private int num = 1;
-
- public void printNum(){
- System.out.println(OuterClass.this.num);
- }
- }
-
- //外部类的非静态方法须通过外部类对象才能访问,已经有了外部类对象,所以可直接在方法内部创建成员内部类对象
- public void test(){
- InnerClass innerClass = new InnerClass();
- //可直接访问内部类的私有成员
- System.out.println(innerClass.num);
- }
-
- //若是静态外部类方法,则需要在方法内部先创建外部类对象,再通过外部类对象创建成员内部类
- public static void innerClassStatic(){
- InnerClass innerClass = new OuterClass().new InnerClass();
-
- //OuterClass outerClass = new OuterClass();
- //InnerClass innerClass = outerClass.new InnerClass();
-
- }
- }
- //外部类
- public class OuterClass {
- private int num = 2;
-
- //成员内部类
- public class InnerClass{
- private int num = 1;
-
- public void printNum(){
- System.out.println(OuterClass.this.num);
- }
- }
-
- //通过非静态方法返回内部类对象
- public InnerClass getInnerClass(){
- return new InnerClass();
- }
-
- //通过静态方法返回内部类对象
- public static InnerClass getInnerClassStatic(){
- return new OuterClass().new InnerClass();
- }
- }
- //外部其他类
- class OuterOtherClass{
- public static void main(String[] args) {
- //先创建外部类对象,再通过外部类对象创建内部类对象
- OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
- innerClass.printNum();
-
- //通过外部类方法获取内部类对象
- OuterClass outerClass = new OuterClass();
- OuterClass.InnerClass innerClass1 = outerClass.getInnerClass();
- OuterClass.InnerClass innerClassStatic = OuterClass.getInnerClassStatic();
- }
- }
- //外部类
- public class OuterClass {
- //成员内部类
- public class InnerClass{
- private int num = 1;
-
- public void printNum(){
-
- }
- }
- }
-
- //外部其他类
- class ExtendInnerClass extends OuterClass.InnerClass{
- public ExtendInnerClass(OuterClass outerClass){
- //显示调用
- outerClass.super();
- }
- }
- //外部类
- public class OuterClass {
- private int num = 2;
- private static int numStatic = 3;
-
- //静态内部类
- public static class InnerClass{
- private int numStatic = 1;
-
- public void printNum(){
- //能直接访问外部类的静态成员
- //若与外部类成员重名,则遵循就近原则
- System.out.println(numStatic);
- //访问外部类静态成员,通过外部类名.成员
- System.out.println(OuterClass.numStatic);
- //若想访问外部类的非静态成员,则需要通过外部类对象访问
- OuterClass outerClass = new OuterClass();
- System.out.println(outerClass.num);
- }
- }
- }
- //外部类
- public class OuterClass {
- private int num = 2;
- private static int numStatic = 3;
-
- //静态内部类
- public static class InnerClass{
- private int numStatic = 1;
- }
-
- public static void main(String[] args) {
- InnerClass innerClass = new InnerClass();
- //可访问内部类所有成员,包括所有
- System.out.println(innerClass.numStatic);
- }
- }
- //外部类
- public class OuterClass {
- private int num = 2;
- private static int numStatic = 3;
-
- //静态内部类
- public static class InnerClass{
- private int numStatic = 1;
-
- public void printNum(){
-
- }
- }
-
- //通过非静态方法返回内部类对象
- public InnerClass getInnerClass(){
- return new InnerClass();
- }
-
- //通过静态方法返回内部类对象
- public static InnerClass getInnerClassStatic(){
- return new InnerClass();
- }
- }
- //外部其他类
- class OuterOtherClass{
- public static void main(String[] args) {
- //直接创建内部类对象访问
- OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
- innerClass.printNum();
- //通过外部类方法返回内部类对象访问
- OuterClass outerClass = new OuterClass();
- outerClass.getInnerClass().printNum();
- OuterClass.getInnerClassStatic().printNum();
- }
- }
- //外部类
- public class OuterClass {
- public int num = 3;
-
- public static class InnerClassStatic{
- public void test(){
- System.out.println("InnerClassStatic");
- }
- }
- }
- //外部其他类
- class ExtendInnerClassStaic extends OuterClass.InnerClassStatic{
- public static void main(String[] args) {
- OuterClass.InnerClassStatic innerClassStatic = new ExtendInnerClassStaic();
- innerClassStatic.test();
- }
- }
- public class OuterClass {
- private int out;
-
- public void test(){
- final int k = 2;
-
- //局部内部类
- class C{
- public void testK(){
- //局部内部类访问局部变量k,若局部变量K不声明final,则编译器会默认加上final修饰符
- System.out.println(k);
- }
- }
- C c = new C();
- c.testK();
- }
-
- }
- //外部类
- public class OuterClass {
- private int num = 2;
- private static int numStatic = 3;
-
- public void test(){
- //局部内部类,只能在定义的作用域使用
- class InnerClass{
- private int num = 4;
- public void test(){
- //若与外部类成员重名,遵循就近原则
- System.out.println(num);
- //通过外部类.this.成员访问外部类的成员
- System.out.println(OuterClass.this.num);
- //访问外部类的静态成员
- System.out.println(OuterClass.numStatic);
- }
- }
- }
-
- public static void testStatic(){
- //局部内部类,只能在定义的作用域使用
- class InnerClass{
- private int numStatic = 5;
-
- public void test(){
- //若与外部类静态成员重名,则遵循就近原则
- System.out.println(numStatic);
- //在静态方法中定义局部内部类,则只能直接访问外部类的静态成员
- System.out.println(OuterClass.numStatic);
- }
- }
- }
-
- public static void main(String[] args) {
- OuterClass outerClass = new OuterClass();
- outerClass.test();
-
- OuterClass.testStatic();
- }
- }
- //外部类
- public class OuterClass {
- private int num = 2;
- private static int numStatic = 3;
-
- public void test(){
- //局部内部类,只能在定义的作用域使用
- class InnerClass{
- private int num = 4;
- public void test(){
-
- }
- }
- //外部类访问局部内部类,只能在作用域内访问
- InnerClass innerClass = new InnerClass();
- innerClass.test();
- }
-
- public static void testStatic(){
- //局部内部类,只能在定义的作用域使用
- class InnerClass{
- private int numStatic = 5;
-
- public void test(){
-
- }
- }
- //外部类访问局部内部类,只能在作用域内访问
- InnerClass innerClass = new InnerClass();
- innerClass.test();
- }
-
- public static void main(String[] args) {
- OuterClass outerClass = new OuterClass();
- outerClass.test();
-
- OuterClass.testStatic();
- }
- }
- public void test(){
- final int k = 2;
-
- B b = new B() {
- @Override
- public void test1() {
- //访问局部变量k,若局部变量k没声明final,编译器会自动加上final
- System.out.println(k);
- }
- };
- }
语法:
- //若是创建类的匿名内部类对象,则参数列表就是类的构造器方法的参数列表
- new 类或接口(参数列表){
- 类体
- };
若匿名内部类在外部类的非静态成员位置时,可直接访问外部类的所有静态、非静态成员,包括私有的成员。
因为通过反编译字节码文件,可发现创建匿名内部类对象时,会将外部类对象传给匿名内部类对象。
- public class OuterClass {
- private int out;
-
- //非静态成员属性位置
- private B b = new B() {
- @Override
- public void test1() {
- //可直接访问外部类的成员
- System.out.println(out);
- }
- };
-
- //非静态成员方法位置
- public void test(){
- B b = new B() {
- @Override
- public void test1() {
- //可直接访问外部类的成员
- System.out.println(out);
- }
- };
- }
- }
-
- interface B{
- void test1();
- }
反编译其中一个匿名内部类的字节码文件如图

若匿名内部类在外部类的静态成员位置时,则只能直接访问外部类的静态所有成员。
- public class OuterClass {
- private static int outStatic;
- //静态成员位置
- private static B b = new B() {
- @Override
- public void test1() {
- }
- };
- }
-
- interface B{
- void test1();
- }
反编译匿名内部类的字节码文件如图
实现接口的匿名内部类
- package com.mzp.test.inner;
-
- public class OuterClass {
- public static void main(String[] args) {
- TestInterface testInterface = new TestInterface() {
- @Override
- public void test() {
- System.out.println("testInterface");
- }
- };
- testInterface.test();
- }
-
- }
-
- interface TestInterface {
- void test();
- }
-
反编译如图

抽象类的匿名内部类
- package com.mzp.test.inner;
-
- public class OuterClass {
- public static void main(String[] args) {
- TestAbstractClass testAbstractClass = new TestAbstractClass() {
- @Override
- public void test() {
- System.out.println("testAbtractClass");
- }
- };
- testAbstractClass.test();
- }
- }
-
- abstract class TestAbstractClass{
- public abstract void test();
- }
反编译如图

普通类的匿名内部类
- public class OuterClass {
- public static void main(String[] args) {
- TestClass testClass = new TestClass(){
- public void test(){
- System.out.println("testClass");
- }
- };
- testClass.test();
- }
- }
-
- class TestClass{
- public void test(){
- System.out.println("test");
- }
- }
反编译如图

参考
内部类系列1(JAVA基础)_chi_666的博客-CSDN博客