什么是内部类
就是在一个类中又定义了另一个类
分类
实例内部类
即未被static修饰的内部类
1.外部类中的任何成员都可以在内部类里面直接访问,不管这个成员是什么权限
2.内部类对象的创建必须是在有外部类成员的前提下
这是错误的,那如何实例化呢?
先要有一个外部类对象,然后再实例化内部类对象,等号左边是这个对象的类型,即OutClass.InnerClass,等号右边则是通过外部类对象去实例化内部类对象
也可以按照下面的方式:
实际上,内部类也是外部类的一个普通成员变量,它是未被static修饰的成员变量,所以它的使用是要依赖外部类对象的
3.内部类里面不能有static修饰的变量,除非加上final
这是因为,内部类的实例必须要有外部类对象的帮助,而static是不依赖对象的
如果说可以有static修饰的成员,那我们就可以用内部类类名.变量来访问这个static变量,但是上面的第二点说了,内部类的加载是要依赖外部类对象的,也就是要想用这个内部类,就必须进行实例化,这就与我们的静态变量的初衷相违背了
但要想用static修饰,就要加上final,因为final修饰的变量会在编译时就被看作常量处理,直接用确定的值来替代,就免去了类加载这一个环节
4.内部类如何访问外部类的成员
当变量名不相同时,直接访问即可
当变量名相同时,要用到this,例如:在外部,a=111;在内部,a=1;下面代码:
会打印出:
为什么不是111呢?修改代码:
这是就可以打印出111了
这是因为,在内部类中隐藏了俩个this,一个时外部的,一个是内部的,这也是为什么对于不重名的变量,直接访问即可,而不需要通过外部类对象或类名来调用,其实就是有了this了,其实实际上this就是一个对象了
而对于外部类的方法,在内部类中也是用上面的方式来调用(不论是否是静态的):
5.外部类如何访问内部类的成员
因为内部类是外部类的一部分,所以直接在非静态方法中实例化一个内部类对象即可
但注意,如果这个外部类的方法是一个静态的,就无法实例化内部类对象了
这是因为,内部类对象的创建依赖外部类对象,如果是一个非静态方法,那么他就有一个隐藏的参数this表示外部对象的引用,但如果是一个静态的方法,就没有this参数,所以就无法对内部类对象进行实例化
静态内部类
被static修饰的内部成员类称为静态内部类
1.在静态内部类中不可以直接访问非静态的外部类成员
由于静态内部类是外部类的一个静态成员,它就和普通静态成员一样,是不依赖对象的,这就导致它的所有方法里面没有隐藏的this参数,所以就无法访问非静态的外部类成员变量和方法
那如何访问呢,只要实例化一个外部类对象即可
2.对于静态的外部类变量和方法,可以直接访问,既不需要实例化外部类对象,也不需要用类名来引出,不论这个内部类方法是否为静态方法
3.外部类的方法如何访问内部类成员
不论这个外部类方法是否为静态的,它要想访问内部类的非静态成员,就必须实例化内部类对象,因为非静态成员依赖对象
而不论这个外部类方法是否为静态的,它要想访问内部类的静态成员,不需要实例化内部类对象,只需要用类名引出即可
4.如何在外部类之外创建静态内部类对象
由于静态内部类同外部类的普通静态成员一样不依赖对象,所以只需要用类名引出即可,如下:
局部内部类
就是定义在外部类的方法体中或者{}中,它只能在对应的方法中使用,不能被static,public等访问修饰限定符修饰。
但注意,final不是访问修饰限定符,所以它可以被final修饰
匿名内部类
我们知道,对于一个接口,是不能直接实例化对象的:
但下面的方法却可以:
这实际上相当于创建了一个匿名对象,实现了IA接口,重写了它的方法
那如何调用这个重写的方法呢?
如上,可以用IA的引用来接收这个内部类对象,这实际上是向上转型,而在调用test方法时则发生了动态绑定
如上,也可以不接收,而是直接调用
其实不用匿名内部类,而是用局部内部类也可以,但不如匿名内部类简洁