前言
每次看到内部类都感觉很陌生,但是感觉又有点熟悉,今天就详细了解一下内部类。
转载自:原文:https://blog.csdn.net/hacker_zhidian/article/details/82193100
内部类可以分为四种,分别为普通内部类、静态内部类、匿名内部类和局部内部类,接下来一一介绍。
1.普通内部类
普通内部类是比较常见的内部类,定义简单,如下:
1|public class OuterClass {
2|
3| public class InnerClass {
4|
5| }
6|}
普通内部类对象依赖外部类对象而存在,即在创建一个普通内部类对象时首先需要创建其外部类对象。内部类对象可以访问外部类对象中所有访问权限的字段,同时,外部类对象也可以通过内部类的对象引用来访问内部类中定义的所有访问权限的字段。如下:
OuterClass outer = new OuterClass();//创建外部类对象
InnerClass inner = outer.new InnerClass();//通过外部类对象创建内部类对象
2.静态内部类
一个类的静态成员独立于这个类的任何一个对象存在,只要在具有访问权限的地方,我们就可以通过 类名.静态成员名 的形式来访问这个静态成员,同样的,静态内部类也是作为一个外部类的静态成员而存在,创建一个类的静态内部类对象不需要依赖其外部类对象。
1|public class OuterClass {
2|
3| static class InnerClass {
4|
5| }
6|}
不需要依赖外部类,直接实例化就行。例如:
InnerClass inner = new InnerClass()
静态内部类就像外部类的一个静态成员一样,创建其对象无需依赖外部类对象(访问一个类的静态成员也无需依赖这个类的对象,因为它是独立于所有类的对象的)。但是于此同时,静态内部类中也无法访问外部类的非静态成员,因为外部类的非静态成员是属于每一个外部类对象的,而本身静态内部类就是独立外部类对象存在的,所以静态内部类不能访问外部类的非静态成员,而外部类依然可以访问静态内部类对象的所有访问权限的成员,这一点和普通内部类无异。
3.匿名内部类
匿名内部类有多种形式,其中最常见的一种形式莫过于在方法参数中新建一个接口对象 / 类对象,并且实现这个接口声明 / 类中原有的方法了。例如:
public class OuterClass {
//自定义接口
interface test () {
void change();
}
//在这个过程会创建一个匿名内部类对象,这个匿名内部类实现了test接口
//并重写了change方法
test t = new test(){
@override
public void change(){
//可以在内部类定义属性,但只能在当前内部类使用,
//因为此内部类没有类名,所以外部类无法调用
int num = 1;
System.out.println("nice")
}
}
}
创建匿名内部类两种方式:
1、直接 new 一个接口,并实现这个接口声明的方法,在这个过程其实会创建一个匿名内部类实现这个接口,并重写接口声明的方法,然后再创建一个这个匿名内部类的对象并赋值给前面的 OnClickListener 类型的引用;
2、new 一个已经存在的类 / 抽象类,并且选择性的实现这个类中的一个或者多个非 final 的方法,这个过程会创建一个匿名内部类对象继承对应的类 / 抽象类,并且重写对应的方法。
同样的,在匿名内部类中可以使用外部类的属性,但是外部类却不能使用匿名内部类中定义的属性,因为是匿名内部类,因此在外部类中无法获取这个类的类名,也就无法得到属性信息。
4.局部内部类
局部内部类使用的比较少,其声明在一个方法体 / 一段代码块的内部,而且不在定义类的定义域之内便无法使用,其提供的功能使用匿名内部类都可以实现,而本身匿名内部类可以写得比它更简洁,因此局部内部类用的比较少。
在局部内部类里面可以访问外部类对象的所有访问权限的字段,而外部类却不能访问局部内部类中定义的字段,因为局部内部类的定义只在其特定的方法体 / 代码块中有效,一旦出了这个定义域,那么其定义就失效了,就像代码注释中描述的那样,即外部类不能获取局部内部类的对象,因而无法访问局部内部类的字段