Skip to content

内部类

内部类,指的是一个类在另一个类的内部中定义。

根据类定义的位置,可以分为以下几种:

  • 成员内部类(常规内部类)
  • 局部内部类
  • 匿名内部类
  • 静态内部类

成员内部类(常规内部类)

成员内部类是直接定义在另一个类的内部,与类成员并列。

特点:

  • 成员内部类可以访问外部类的所有成员,包括私有属性。
  • 在成员内部类中要想访问外部类的成员,可以通过外部类.this.外部类成员进行访问
  • 成员内部类中的属性和方法不能是静态的
  • 创建成员内部类的对象时,需要外部类的对象存在
  • 含有内部类的类文件经过源码编译后,除了外部类的字节码,还会产生内部类的字节码,格式为外部类$内部类.class
java
package innerclass;

public class Demo {
    private String name = "这是正常类中的属性";
    public void testDemo() {
        System.out.println("这是正常类中的方法");
    }

    // 成员内部类
    public class InnerDemo {
        private String name = "这是成员内部类的属性";
        public void testInnerDemo() {
            System.out.println("这是成员内部类的方法: " + this.name);
            Demo.this.testDemo();
            System.out.println("在成员内部类中访问外部类的私有属性: " + Demo.this.name);
        }
    }
}
java
package innerclass;
import innerclass.Demo.InnerDemo;

public class Test {
    public static void main(String[] args) {
        Demo d = new Demo();
      	// 创建成员内部类的对象时,需要外部类的对象存在
        InnerDemo iD = d.new InnerDemo();
        iD.testInnerDemo();
    }
}

局部内部类

局部内部类是在外部类的方法或程序块中定义的,与局部变量并列。

特点:

  • 局部内部类相当于一个变量,具有临时性,因此不能用 public、protected、private 和 static 修饰

  • 局部内部类只可以直接访问方法中被 final 修饰的变量

  • 在不同的方法中定义同名的局部内部类时,它们的字节码格式为外部类$1内部类.class外部类$2内部类.class....

java
package innerclass;

public class Demo {
    private String name = "这是正常类中的属性";
    public void testDemo() {
        System.out.println("这是正常类中的方法");
    }
    public void testDemoPart() {
        // 局部内部类,临时性存在
        class PartInnerDemo {
            private String name = "这是局部内部类的属性";
            public void testPartInnerDemo() {
                System.out.println("这是局部内部类的方法: " + this.name);
            }
        }
        PartInnerDemo pID = new PartInnerDemo();
        pID.testPartInnerDemo();
    }
  	public static void main(String[] args) {
      Demo d = new Demo();
      d.testDemoPart();
    }
}

匿名内部类

匿名内部类通常表现为接口或抽象类的具体子类。

特点:

  • 匿名内部类只有类体,没有类的所有结构(修饰符、类名、继承、实现)
  • 匿名内部类没有构造方法

常规的接口与子类实现如下:

java
public interface Animal {
  void eat();
}

public class Dog implements Animal {
  void eat() {
    System.out.println("狗吃骨头");
  }
}

public class Test {
  public static void main(String[] args) {
    Anima a = new Dog();
    a.eat();
  }
}

而匿名内部类则省略了类名:

java
public interface Animal {
  void eat();
}

public class Test {
  public static void main(String[] args) {
    Animal dog = new Animal(){
      void eat() {
        System.out.println("狗吃骨头");
      }
    };
    dog.eat();
  }
}

静态内部类

静态内部类跟成员内部类相似,区别在于静态内部类多了一个 static 修饰符,因此在创建静态内部类对象时,不需要借助外部类的对象,可以直接创建。

特点:

  • 静态内部类只能访问外部类的静态成员
java
package innerclass;

public class Demo {
    private String name = "这是正常类中的属性";
    public void testDemo() {
        System.out.println("这是正常类中的方法");
    }
  
  	public static class StaticInnerDemo {
      private String name = "这是静态内部类的属性";
      public void testStaticInnerDemo() {
        System.out.println("这是静态内部类的方法: " + name);
      }
    }
  	public static void main(String[] args) {
      Demo.StaticInnerDemo sID = new Demo.StaticInnerDemo();
      sID.testStaticInnerDemo();
    }
}