其实外部类和内部类是一个相对的定义。
类A中有类B,那么类A自然就是外部类了,类B就是内部类。
外部类的访问权限只有两种:public和(default)。
但是内部类因类型不同所以对应的访问权限也不一样。
内部类可以使用外部类的任何变量和方法,但是外部类必须要实例化内部类才可以使用内部类。
而且在实例化之前必须先创建一个外部类的实例。
不过也可以使用this来调用外部类和内部类的元素。
内部类分为成员内部类,匿名内部类、局部内部类和静态内部类。
① 成员内部类
成员内部类其实就是最简简单单的那种内部类了,定义在一个类的内部。
public class MemInner {
int num = 10;
public static void main(String[] args) {
MemInner mi = new MemInner();
Inner in = mi.new Inner();
System.out.println(in.num);
in.systemOut();
}
public class Inner{
int num = 9;
public void systemOut(){
System.out.println(num);
System.out.println(MemInner.this.num);
}
}
}
如果外部类想要调用内部类,先要实例化内部类相对的外部类,然后再实例化目标内部类,然后才能访问里面的成员变量和方法。
并且如果想要访问内部类和外部类同名的成员变量或成员方法,需要按照以下格式访问:
外部类.this.成员变量
外部类.this.成员方法
而且无论外部类的成员变量或成员方法的访问权限是什么,内部类统统都可以访问。
② 局部内部类
局部内部类是定义在方法或者是一个作用域上面的类,它和成员内部类的区别就在于局部内部类的访问权限仅在定义它的这个方法或者作用域里面(访问范围缩小)。
public class AreaInner {
int num = 9;
public static void main(String[] args) {
AreaInner ai = new AreaInner();
ai.Inner();
}
public void Inner(){
String name = "黄花大闺女";
class AInner{
void call(){
System.out.println(num);
System.out.println(name);
}
}
AInner an = new AInner();
an.call();
}
}
就像是main()函数调用不了方法中的局部变量一样,如果想要在外部类实例化局部内部类,首先要在这个方法或者作用域里面提前实例化此内部类,然后在外部类调用其方法或者作用域的时候,就可以真正为这个内部类提供资源空间。
③ 匿名内部类
匿名内部类在用作监听器的时候是一个非常方便的写法,而且匿名内部类有两个特点:无构造器,不可使用static等限定词。
buttons[0].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
});
使用匿名内部类之后就不需要在外部类重新实例化了,方便好用。
④ 静态内部类
静态内部类跟成员内部类的区别就在于有没有"static"修饰,然后因为是静态类,所以要能访问的只有外部类中被static修饰过的成员变量或者方法。
public class StaticInner {
int num = 9;
static String name = "黄花大闺女";
Inner i = new Inner();
static class Inner{
void call(){
System.out.println(num); //会报错
System.out.println(name);
}
}
}
在没有外部类的情况下是可以直接创建静态内部类实例的,但是如果要使用外部类的非静态成员变量或成员方法,还是需要创建外部类实例才可以使用。
补充:内部类小结(参考自https://www.nowcoder.com/test/question/done?tid=17994589&qid=112853#summary)
-|内部类:
-|静态内部类:不可访问外部的非静态资源
-|但是可以有public static abstract class Demo
-|成员内部类:可以访问外部所有资源,但是本身内部不可有静态属性(因为自己本身就需要依靠外部类的实例化)
-|局部内部类:不可被访问修饰符和static修饰,只能访问final变量和形参
-|局部静态内部类:在外部类的静态方法中
-|局部内部类:在外部类的一般方法中
-|匿名内部类:没有构造器,没有静态资源,无法被访问修饰符、static修饰;只能创建匿名内部类的一个实例;创建的时候一定是在new的后面