内部类
或嵌套类,在一个类(或方法、代码块)的内部定义另一个类。封装它的类为外部类。
作用:封装、提供命名空间、便于访问外部类成员
分类:有名内部类(局部nbl、成员nbl(实例成员nbl、静态成员nbl))、匿名内部类
成员内部类
类似于外部类的成员变量,是在外部类的内部,且方法体和代码块之外定义的内部类。
实例成员内部类
与实例变量类似,4种访问级别都可以,而外部类只能声明为公有或默认
// 外部类
public class Outer {
// 外部类成员变量
private int x = 10;
// 外部类方法
private void print() {
System.out.println("调用外部方法");
}
// 调用内部类
public void test() {
Inner inner = new Inner();
inner.display();
}
// 内部类
class Inner {
private int x = 5;
void display() {
System.out.println("外部类成员变量" + Outer.this.x);
System.out.println("内部类成员变量" + this.x);
System.out.println("内部类成员变量" + x);
// 调用外部类的成员方法
Outer.this.print();
print();
}
}
}
public class HelloWorld {
public static void main(String[] args) {
// 通过外部类访问内部类
Outer outer = new Outer();
outer.test();
// 直接访问内部类
Outer.Inner inner = outer.new Inner();
inner.display();
}
}
通常情况下使用实例成员内部类不是给外部类之外调用使用的。
内部类编译成功后生成的字节码文件是“外部类$内部类.class”
静态成员内部类
与静态变量类似,生声明时使用static修饰
只能访问外部类静态成员(所以使用场景不多),但可以提供有别于包的命名空间
public class View {
private static int staticX = 10;
static class Button {
void onClick() {
System.out.println(staticX);
}
}
}
局部内部类
在方法体或代码块中定义的内部类
访问级别只能是默认的,不能是静态的(不能用static)
public class Outer {
private int value = 10;
public void add(final int x, int y) {
int z = 100;
// 内部类
class Inner {
// 内部类方法
void display() {
// 注意:这里的x要声明为final的
int sum = x + z + value;
}
}
new Inner().dispaly(); // 声明匿名对象
}
}
匿名内部类
没有名字,本质是没有名的局部内部类(具有局部内部类的所有特征)。
如果匿名内部类在方法中定义,它所访问的参数需声明为final的。
// 接口
public interface OnClickListener {
void onClick();
}
public class View {
public void handler(OnClickListener listener) {
listener.onClick();
}
}
public class HelloWorld {
public static void main(String[] args) {
View v = new View();
// 方法参数是匿名内部类
// new是为匿名内部类创建对象,()是调用构造方法,{}是类体
v.handler(new OnClickListener() {
@Override
public void onClick() {
System.out.println("实现接口的匿名内部类");
}
});
// 继承类的匿名内部类(Figure是抽象类)
// 在赋值时使用匿名内部类
Figure f = new Figure() {
@Override
public void onDraw() {
System.out.println("继承类的匿名内部类");
}
}; // 注意分号
// 具体类作为内部类
Person person = new Person("Tony", 18) {
@Override
public String toString() {
return "匿名内部类实现" + name + age;
}
}; // 注意分号
// 打印过程自动调用person的toString()方法
System.out.println(person);
}
}
匿名内部类通常用来实现接口或抽象类,很少覆盖具体类。
注意!关于内部类后是否加分号:
定义一个类的代码,不需要加分号。
实例化一个类的时候需要加分号,因为算一个语句。