目录
一、基本概念
内部类(inner class)是定义在另一个类中的类。和类的变量、方法一样,内部类是一个类的成员。同时内部类也可以拥有其他的类作为它的成员。
为什么要使用内部类而不是单独的的类呢?
- 假设一个类只对某个类有用,那么可以在逻辑上将它嵌入到该类中,使他们保持在一起。这样,包结构会更精简。
- 假设有两个类C1和C2,C2需要访问C1的私有成员。将C2嵌套到C1中,C1的成员被定义为私有的,C2可以访问这些私有的数据。
- 内部类为定义回调提供了一种方便的方法。
二、使用内部类访问对象状态
内部类既可以访问自身的数据域,也可以访问创建它的外部类对象的数据域。
使用一个简单的例子来分析:
public class C1 {
private String name = "class C1";
class C2{
public String getName(){
return name;
}
}
public static void main(String[] args) {
//创建外部类的对象
C1 outerClz = new C1();
//创建内部类的对象
C1.C2 innerClz = outerClz.new C2();
System.out.println(innerClz.getName());
}
}
调试代码可以看出在C2的getName函数中name引用的是C1对象的域。
根据内部类的语法规则,也可以使用outerClass.this来表示外部类引用。
return C1.this.name;
知识点:常规类只能具有包的可见性(不加权限修饰符)或者公有的可见性(public)。内部类可以是私有类(private)。
如果将常规类定义为private类,编译的时候会报错:Modifier 'private' not allowed here。
如果将内部类定义为priviate类,只有其所在的外部类可以访问,其他类无法访问。
三、局部内部类
如果内部类只在外部类的某一个方法中使用时,可以在该方法里面定义局部类。
此时,局部类不能使用public或者private修饰符。编写代码时,IDE会提示错误。
使用局部类的优点:
- 除了定义局部类的方法,其他类或方法无法访问它,也不知道它的存在。
四、匿名内部类
假设在一些使用场景中,只需要创建类的对象,不需要为类命名,这种类就是匿名内部类。
比如上面的Printer局部类,可以经过下面的改造,变成匿名内部类。
注意:
匿名类不能有构造器;-> 因为它没有类名
实现接口的时候,不能有构造参数;
使用匿名内部类会使代码看起来更简短,但有时候也会让程序更加难理解。
知识点:
在JDK8之前,局部内部类、匿名内部类访问外部类方法的局部变量需要用final修饰符。JDK8及以后的版本,不再有这个限制。
以下面这段代码为例,
如果使用的是JDK8(+)版本,可以编译运行。
如果使用的是JDK8之前的版本,无法通过编译。
需要将局部变量a和c声明为final变量。
五、静态内部类
内部类可以被定义为静态的,而常规类不能定义成static的。假设内部类不需要引用外部类对象,那么可以将该内部类定义成static的。