内部类就是在一个类内部进行其他类结构的嵌套操作,这样设计的目的在于将某些特殊用途的类进行封装,比如B
类只是给A
类使用,那么我们将B
类定义为A
类的内部类,整体的代码逻辑就十分简洁。
内部类一样可以使用权限修饰符,public
、private
、protected
都可以使用。
1. 普通内部类
普通内部类是无法在当前类以外的地方进行直接实例化,下面示例中在主函数程序中直接使用new Inner();
是错误的,如果非要使用可以采用new Outter().new Inner();
这样的方式:
public class Outter {
public Outter() {
System.out.println("Outter");
}
public class Inner {
public Inner() {
System.out.println("Inner");
}
}
public void printInner() {
new Inner();
}
public static void main(String[] args) {
new Outter();
new Outter().printInner();
}
}
代码成功编译后,会产生两个文件 Outter$Inner.class 和 Outter.class,可以明显地看出这是两个类文件,这也表明了不会在同一加载流程中:
❯ ls -la
Outter$Inner.class Outter.class
2. 静态内部类
显然new Outter().new Inner();
这样的调用方式太反人类了,我们期望使用方式类似new Outter.Inner();
,这种调用格式与之前的静态方法很一致,称之为静态内部类:
public class Outter {
public Outter() {
System.out.println("Outter");
}
public static class Inner {
public Inner() {
System.out.println("Inner");
}
}
public void printInner() {
new Inner();
}
public static void main(String[] args) {
new Outter.Inner();
}
}
💡 注意点 —————
- 静态内部类只会在第一次实例化时才会加载一次,否则不会加载。
- 类内部的属性和方法如果不加
static
的话,它就是属于实例对象的。
3. 匿名内部类
匿名内部类可以让代码更加简洁,我们可以在定义一个类时同时实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类我们只使用一次,那么匿名内部类就非常适合使用。
匿名类是一个表达式,语法就类似于调用一个类的构造函数(new HelloWorld()
),并包含了一个完善类定义的 代码块:
| ```java wolf.eat(new Animal() { @Override public void eat(Animal animal) { System.out.println(this.getName()
+ "likes eating " + animal.getName());
}
@Override
public String getName() {
return "sheep";
}
});
| ```java
tigger.eat(new Wolf() {
@Override
public void eat(Animal animal) {
super.eat(animal);
}
@Override
public String getName() {
return "wolf";
}
});
| | —- | —- |