定在类内部的类叫做内部类,内部类根据定义的方式不同,分为四种:

  • 静态内部类
  • 成员内部类
  • 局部内部类
  • 匿名内部类

静态内部类

静态内部类的代码实现如下

  1. /**
  2. * <p> 静态内部类实现模拟 </p>
  3. *
  4. * @author zhixing
  5. */
  6. public class Outer {
  7. private static String name = "outer";
  8. private String add = "earth";
  9. /** 静态内部类 **/
  10. public static class Inner{
  11. public void printOuterName(){
  12. System.out.println("Outer name:" + name);
  13. }
  14. }
  15. }

内部类特点

  • 静态内部类可以访问外部类所有的静态变量和方法,private 照样访问
  • 静态内部类和一般类一样,可以定义变量,方法,构造函数等。
  • 其他类使用静态内部类的方法 Outer.Inner inner = new Outer.Inner();
    class Test{
    public static void main(String[] args) {
    Outer.Inner inner = new Outer.Inner();
    inner.printOuterName();
    }
    }
    

使用场景:与外部类关系密切,不依赖外部类实例,都可以使用静态内部类。例如:HashMap 中的 Node。

成员内部类

定义在类内部的非静态的类,叫做成员内部类。

成员内部类不能定义除 final修饰外的静态变量和静态方法。(如果成员内部类能够定义静态变量,那成员内部类的静态变量初始化顺序会存在歧义)

相关代码实现如下

public class Outer {
    private static String name = "outer";
    private String add = "earth";

    /** 成员内部类 **/
    public class Inner{
      // 报错:Inner classes cannot have static declarations
      //private static int num = 1;

      // 正确
      private static final int num = 1;

        public void printOuterName(){
            System.out.println("Outer name:" + name);
        }
        public void printOuterAdd(){
            System.out.println("Outer add:" + add);
        }
    }
}

class Test{
    public static void main(String[] args) {
        Outer outer = new Outer();
        // 成员内部类,依赖于外部类,只能通过实例化的外部类,才能进行实例化
        Outer.Inner inner = outer.new Inner();
        inner.printOuterName();
        inner.printOuterAdd();
    }
}

局部内部类

定义在方法中的类,就是局部类。

使用场景:如果一个类只在某个方法中使用,可以使用局部类。

代码如下:

public class Outer {
    private static String name = "outer";
    private String add = "earth";

    public void print(){
        class Inner{
            public void printName() {
                System.out.println("outer name:" + name);
            }
            public void printAdd(){
                System.out.println("outer add:" + add);
            }
        }
        Inner inner = new Inner();
        inner.printAdd();
        inner.printName();
    }
}

class Test{
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.print();
    }
}

匿名内部类

要继承一个父类或者实现一个接口,直接使用 new 来生成一个对象的引用,并且只继承一份父类或者实现一个接口。
同时它没有 class 关键字,因为匿名内部类直接使用 new 来生成一个对象的引用。

直接上代码

public class Bird {
    public Bird(String name, int age) {
        this.name = name;
        this.age = age;
    }
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Bird{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class Test{
    public static void main(String[] args) {
        // jdk 8 默认的 Consumer 使用 lambda 表达式的匿名内部类
        Consumer<Bird> consumer = (bird)->{
            System.out.println(bird);
        };
        // 匿名内部类
        consumer.accept(new Bird("小鸟",20));
    }
}