内部类分为4种
- 成员内部类(非静态内部类)
- 局部内部类
- 静态内部类
- 匿名内部类
成员内部类(member inner class)非静态内部类
- 定义在外部类里面不使用static修饰
- 成员内部类相当于外部类的成员,内部类可以访问外部类一切成员
- 编译之后生成.class文件: OutterClass$InnerClass.class
- 内部类不可以有静态成员
案例
- package com.itlwc;
- class OutterClass {
- int x = 100;
- class InnerClass {
- int x = 50;
- public void show() {
- //使用预定义对象引用this
- System.out.println("调用外部类成员x = " + OutterClass.this.x);
- System.out.println("调用成员内部类成员x = " + this.x);
- }
- }
- }
- public class Test {
- public static void main(String[] args) {
- //生成对象的方法
- OutterClass.InnerClass ocic = new OutterClass().new InnerClass();
- ocic.show();
- }
- }
- /*
- 打印结果:
- 调用外部类成员x = 100
- 调用成员内部类成员x = 50
- */
局部内部类(local inner class)
- 定义在方法中
- 局部内部类只能访问局部final的成员
案例
- package com.itlwc;
- class OutterClass {
- public void getInnerClass() {
- // 局部内部类只能访问final的变量
- final int x = 0;
- class InnerClass {
- public void show() {
- System.out.println("局部内部类的方法" + x);
- }
- }
- InnerClass ic = new InnerClass();
- ic.show();
- }
- }
- public class Test {
- public static void main(String[] args) {
- OutterClass oc = new OutterClass();
- oc.getInnerClass();
- }
- }
- /*
- 打印结果:
- 局部内部类的方法0
- */
静态内部类(static inner class)
- 定义在类的里面使用static关键字
- 编译之后生成.class文件: OutterClass$InnerClass.class
- 静态内部类只能访问静态成员
- 静态内部类不能使用this
- package com.itlwc;
- class OutterClass {
- static class InnerClass {
- public void show() {
- System.out.println("静态内部类的方法");
- }
- }
- }
- public class Test {
- public static void main(String[] args) {
- //生成对象的方法
- OutterClass.InnerClass oi = new OutterClass.InnerClass();
- oi.show();
- }
- }
- /*
- 打印结果:
- 静态内部类的方法
- */
非静态内部类和静态内部类的区别
- 非静态内部类与外部类对象成员存在共享关系,是外部类的组成部分,用来辅助工作
- 静态内部类与外部类之间没有这样的关系,静态内部类已经脱离了外部类的控制,
- static关键字只是说明创建对象不依赖外部类的引用的存在,并不是说这个类是静态的
匿名内部类(anonymous inner class)
- 定义:没有名字的内部类
- 匿名内部类没有名称,因此匿名内部类在声明类的同时也创建了对象
- 匿名内部类没有class,名字,extends,implements,构造方法,
- 但它会隐式继承一个父类或者实现一个接口,这两个不能同时(这个是内部类很重要的特点)
- 因为匿名内部类没有名称,没办法声明匿名内部类类型的引用,
- 因此匿名内部类中的成员只能内部使用
- 匿名内部类对象的使用都是通过多态进行的,
- 如果匿名内部类重写了父类方法,可以通过多态让父类的引用调用匿名内部类的方法
- (案例一)
- 匿名内部类编译后也是一个独立的类文件,
- 由于没有名字,使用数字代替,如 OutClass$1.class
- 匿名内部类对象初始化的代码可以写在非静态语句块中
- (案例二)
- package com.itlwc;
- class Father {
- public void show() {
- System.out.println("Father类的方法");
- }
- }
- public class Test {
- public static void main(String[] args) {
- // 定义匿名内部类并创建对象
- Father f = new Father() {
- // 重写了父类的方法
- public void show() {
- System.out.println("匿名内部类的方法");
- }
- };
- // 通过多态调用了父类的引用调用了子类的对象
- f.show();
- }
- }
- /*
- 打印结果:
- 匿名内部类的方法
- */
- package com.itlwc;
- abstract class Father {
- int age;
- abstract void show();
- }
- public class Test {
- public static void main(String[] args) {
- // 定义匿名内部类并创建对象
- Father f = new Father() {
- // 非静态代码块中对成员age进行初始化
- {
- age = 18;
- }
- // 实现父类的方法
- public void show() {
- System.out.println("年龄 = " + age);
- }
- };
- // 通过多态使用父类的引用调用子类对象
- f.show();
- }
- }
- /*
- 打印结果:
- 年龄 = 18
- */
有名字的内部类和匿名内部类的区别
- 如果有两个或者两个方法会使用该类,建议使用内部类
- 如果只有一个方法使用该类,建议使用匿名内部类