内部类:
一个类或者接口定义在另外一个类或者接口的内部,将一个类定义置入另一个类定义中,这就叫做“内部类”。
public class A1{ //外部类
class A2{} //内部类
interface A3{} //内部接口
}
内部类的名称必须区别与它所在的外部类,与其他类之间没有要求;
public class A1 { //外部类
class A2{} //内部类
}
class A2{}
内部类可以访问其外部类的所有变量和方法;(内部类的范围限定词是四种)
内部类比外部类多了protect/private/static三个修饰符,这三个修饰符不能用在外部类上;
非静态内部类不能拥有静态成员和静态方法,静态内部类则没有这个限制
内部类的作用
内部类提供更好的封装
内部类可以直接访问外部类的私有成员,外部类不能直接访问内部类的成员
匿名内部类适合创建仅仅使用一次的类
内部类创建对象
//外部类.内部类 in = new 外部类().new 内部类();
public class A1 { //外部类
public static void main(String[] args) {
A2 a2 = new A2();
A2.A3 aa = new A2().new A3();
}
}
class A2{
class A3{}
}
创建外部类对象和内部类无关,创建外部类对象并不会自动创建内部类对象;
静态内部类
- 静态内部类中,可以有静态数据、静态方法或者有一个静态内部类
- 不需要构建外部类对象,就可以直接创建静态内部类对象,但是是 否可见取决于范围限定词
- 可以直接访问静态内部类中的静态成员,但是是否可见取决于范围限定词
- 静态内部类中,可以有非静态数据,非静态方法或者一个非静态内部类
- 静态内部类中,不能访问外部类的非静态成员(静态方法不能直接访问非静态成员)。
代码实现:
public class A1 { // 外部类
public static void main(String[] args) {
//不需要构建外部类对象,就可以直接创建静态内部类对象,但是是否可见取决于范围限定词
A2.A3 aa = new A2.A3();
//可以直接访问静态内部类中的静态成员,但是是否可见取决于范围限定词
A2.A3.pp();
}
}
class A2 {
static class A3 {
public static void pp(){
System.out.println("pp...");
}
}
}
局部内部类
可以将内部类定义在一个方法或者一个代码块中
注意:局部内部类需要先定义后使用,不能先使用后定义;
public class A1 { // 外部类
private int age = 13;
public static void main(String[] args) {
A1 aa = new A1();
}
public void pp(){
//定义在方法中
class A2{
public void ff(){
System.out.println("hh...");
}
}
//先定义后使用
A2 bb = new A2();
}
}
匿名内部类
匿名内部类就是内部类的简写形式
匿名内部类的前提是必须继承或实现一个外部类或者接口
匿名内部类由于没有名字,所以没有构造函数
如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它时必须要带上这些参数
不能定义静态成员
代码实现:
public class A1 { // 外部类
public void pp() {
Object obj = new Object() {
@Override // 覆盖父类中定义的方法
public String toString() {
return ("anon inner class ... ff");
}
};
System.out.println(obj.toString());// 调用匿名内部类中覆盖定义的方法 } }
}
}
匿名内部类的使用限制:
- 匿名内部类不能是抽象的
- 匿名内部类不能定义构造器,默认和父类相似的构造器
- j要求给局部内部类,匿名内部类访问的局部变量必须用final修饰,从jdk1.8开始这个现实被取消了,但是默认是final的(不能修改);