内部类分为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
*/
有名字的内部类和匿名内部类的区别
如果有两个或者两个方法会使用该类,建议使用内部类
如果只有一个方法使用该类,建议使用匿名内部类