Day16 内部类

发布时间 2023-12-04 17:54:56作者: 问稻

1. 内部类的含义

内部类就是在一个类的内部再定义一个类。比如A类中定义了一个类B,那么 B就是A 的内部类,A是B的外部类

class A{//外部类
    class B{//内部类    
    }
}

内部类可以分为:

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

默认:

  • 如果声明内部类时不使用任何修饰符,那么默认是public static(静态内部类)

  • 声明在接口中的内部类,默认是public static。


2.成员内部类

当内部类是外部类的数据时, 创建内部类对象之前需要先创建外部类对象。

生成一个内部实力的执行顺序为:

1.先加载外部类的静态代码块(按照上下顺序)
2.加载外部类的构造方法
3.加载内部类的构造方法

2.1 如何实例化?

先实例化一个外部类,再通过外部类的实例new 一个内部类的实例,该内部类实例的类型为 Outer.Inner

public class Outer {
    class Inner{}
}

public static void main(String[] args) {
        Outer outer = new Outer();
        //再通过这个外部类的实例来实例化内部类
        Outer.Inner inner = outer.new Inner();
}

2.2 内部类外部类的访问范围

public class Outer {
    private int outerId = 10;
    public void sameOut(){
        System.out.println("这是外部类同名的方法");
    }
    public void outerOut(){
        System.out.println("这是外部类非同名的方法");
    }
    /*public int getInnerId(){//获取内部类的私有属性
        //直接用变量名调用,无需加作用域
        return innerId;//报错中不到innerId
    }*/
   public class Inner{ //内部类也可以是public!!!
        private int innerId = 20;
        public void sameOut(){//与外部类方法同名没报错!
            System.out.println("这是内部类同名的方法");
        }
        public void innerOut(){//与外部类方法同名没报错!
            System.out.println("这是内部类非同名的方法");
        }
        public int getOuterId(){//获取外部类的私有属性
            //直接用变量名调用,无需加作用域
            return outerId;
        }
    }
}
public class main {
    public static void main(String[] args) {
        Outer outer = new Outer();
        //再通过这个外部类的实例来实例化内部类
        Outer.Inner inner = outer.new Inner();

        outer.sameOut();//这是外部类同名的方法
        inner.sameOut();//这是内部类同名的方法

        outer.outerOut();//这是外部类非同名的方法
        inner.innerOut();//这是内部类非同名的方法

        //inner.outerOut();//报错找不到outerOut()
        //outer.innerOut();//报错找不到innerOut()

        //System.out.println(outer.getInnerId());//报错,找不到innerId
        System.out.println(inner.getOuterId());//10
    }
}

根据上述运行结果我们可以得出:

  • 外部类引用无法访问内部类的私有成员或者任何成员函数
  • 内部类引用无法直接访问外部里的任何成员函数,但是可以访问外部类的私有长远函数
  • 外部类、内部类可以有同名的方法,但是外部类、内部类引用会调用各自的方法

3.静态内部类(编译器源码用的比较多)

  • static可以修饰内部类,非内部类不能被它修饰

  • 使用static修饰符修饰的内部类称之为静态内部类,也有人称静态内部类为嵌套类。

  • 创建静态内部类不会加载外部类的静态代码块,不会调用外部类的构造方法,所有内部类无妨访问外部类非静态成员属性(任何非静态变量)。

class A{//外部类
    private int id;
    class static B{//内部类 
        public int getOuterId(){//获取外部类的私有属性
            return id;//报错,静态内部类无法访问外部类的
    }
}

4. 局部内部类(可以认为是函数内部类)

  • 定义在方法内的内部类,我们称之为局部内部类。

  • 局部类不能用public或private修饰符进行声明。它的作用域被限定在声明这个局部类的块中。

  • 局部类有一个优势, 即对外部世界可以完全地隐藏起来。

5.匿名内部类