1、什么是内部类?
定义:将一个类定义在另一个类的里面,对里面那个类就称为内部类(也称为内置类,嵌套类)。例如,把类B定义在类A里面,B就被称为A的内部类。
示例如下:
<span style="font-size:14px;">//定义外部类 class Outer { private int num = 10; //定义内部类 class Inner { public void show() { System.out.println(num); } } }</span>2、内部类的作用及访问特点?
作用:我们知道,如果一个类中定义变量用private修饰,那么外部是不能够直接访问的,这种情况下,如果我们要访问,就可以用到内部类。
访问特点:内部类可以直接访问外部类中的成员,包括私有成员;而外部类要访问内部类中的成员必须要建立内部类的对象。
3、内部类的分类?
按照内部类的定义位置,可以分为成员内部类(定义在外部类的成员位置)、局部内部类(定义在外部类的方法里边)。
(1)成员内部类:
<span style="font-size:14px;">//定义外部类 class Outer { private int num = 10; //定义内部类 class Inner { public void show() { System.out.println(num); } } }</span>以上就是一个成员内部类,它定义在了成员位置(就是和成员变量、成员方法等相同的位置),如果我们要实现对内部类的访问,那么只能是:
<span style="font-size:14px;">class InnerTest { public static void main(String[] args) { //我能不能直接使用Inner类呢?显然是不可以的,因为内部类定义在其它类里边,而虚拟机是看不到类里边的东西的 //Inner i = new Inner(); //会报出找不到该类路径的错误 //i.show(); //所以,正确的格式是:外部类名.内部类名 变量 = 外部类对象.内部类对象; 我们需要经过外部类的限定才能访问内部类 Outer.Inner oi = new Outer().new Inner(); oi.show(); } }</span>值得注意的是,在外面创建内部类对象格式须为:外部类名.内部类名 变量 = 外部类对象().内部类对象();。
(2)局部内部类:
<span style="font-size:14px;">//定义外部类 class Outer { public void method(){ final int num = 10; //定义局部内部类 class Inner{ public void show(){ System.out.println(num); } } //创建对象 Inner i = new Inner(); i.show(); } }</span>注意:如果用成员内部类的方式:外部类名.内部类名 变量 = 外部类对象.内部类对象;来创建局部内部类是不可以的,因为虚拟机也看不到方法里边的东西,无法提供路径,所以必须在方法里边来创建局部内部类的对象,此外局部内部类如果访问局部变量(例如上边的num),局部变量必须被final修饰。
那么为什么必须被final修饰呢?
因为局部变量存储在栈内存中,而栈内存最大的特点是数据使用完后立马消失,所以局部变量会在方法调用完毕后,立马消失。而局部内部类虽然也在方法中,但是new出的对象是存在堆内存中的,所以局部内部类所在的方法调用完毕消失后,局部内部类new出的对象依然存在,所以内部类中定义的方法依然存在,方法依然存在就要要求方法所用到的局部变量存在,所以局部内部类访问的局部变量就不能是使用完后消失的变量,所以要求其被final修饰,作为常量储存在方法区中,不会消失。也就是说,如果有地方使用着局部变量,当方法消失后,这个变量还必须存在。所以,为了延长局部变量的生命周期,就加final修饰了。
4、内部类的常用修饰符?
内部类的常用修饰符为private、static。
(1)private:为了安全考虑。如果将外部类视为body的话,内部类就可以看为这个body的心脏,我们当然不会希望外部可以随意的访问我们的心脏,那么太不安全了,所以我们需要对内部类进行private修饰。那么这个时候,我们只能将对内部类的访问交给外部类的一个方法,然后将这个方法做成public,提供给外部访问。例如:
<span style="font-size:14px;">//定义外部类 class Outer { private int num = 10; //定义内部类 private class Inner { public void show() { System.out.println(num); } } //将对内部类的访问交给method方法来做 public void method() { Inner i = new Inner(); i.show(); } }</span>(2)static:为了调用方便考虑。用静态修饰过的方法和变量可以直接通过类名调用,但是如果成员内部类内部类中方法被static修饰,那么这个成员内部类必须被static修饰,为什么呢?
因为成员内部类定义在外部类的成员位置,可以看成是外部类的成员,是可以被静态修饰的。而静态是随着类的加载而加载的,如果内部类的静态方法被加载时,发现内部类却因为没有被static修饰而无法加载时就会报错。
另外,被static修饰的成员内部类,创建对象的方法就应该是:外部类名.内部类名 变量 = new 外部类名.内部类名();(对比原先的是:new 外部类名().内部类名();),因为被静态修饰,只能通过外部类类名来调用,不能通过外部类对象来调用。
小结:内部类就是定义在类里边的类,是类中类。使用内部类要清楚内部类的作用、访问特点和限制修饰符的各种作用。