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修饰符进行声明。它的作用域被限定在声明这个局部类的块中。
-
局部类有一个优势, 即对外部世界可以完全地隐藏起来。