一、分类
内部类分为以下两种:
- 静态内部类
- 非静态内部类
非静态内部类又分为以下三种:
- 成员内部类
- 方法内部类
- 匿名内部类
二、静态内部类
测试代码如下:
public class Outer {
private String a = "a";
private static String b = "b";
public String c = "c";
public static String d = "d";
private static String e = "e";
private void method1() {
System.out.println("method1");
}
private static void method2() {
System.out.println("method2");
}
public static class Inner {
private static int e = 5;
public static void sayHello() {
// 静态内部类只可以直接访问静态资源,所以编译报错
// System.out.println(a);
System.out.println(new Outer().a);
System.out.println(b);
// 静态内部类只可以直接访问静态资源,所以编译报错
// System.out.println(c);
System.out.println(new Outer().c);
System.out.println(d);
// 静态内部类只可以直接访问静态资源,所以编译报错
// method1();
new Outer().method1();
method2();
// 静态内部类定义和外部类同名的变量时,会使用在静态内部类中定义的变量
System.out.println(e);
}
}
public static void main(String[] args) {
new Outer.Inner().sayHello();
new Inner().sayHello();
// 调用静态内部类的静态方法可以这样用
Inner.sayHello();
}
}
控制台输出如下:
a
b
c
d
method1
method2
5
结论:
- 静态内部类的调用方法:
new Outer.Inner().sayHello()
、new Inner().sayHello()
、Inner.sayHello()
- 静态内部类能直接访问到外部类的静态资源,但不可以直接访问外部类的非静态资源(可以借助外部类的实例对象访问)。
- 静态内部类定义和外部类同名的变量时,当使用时会调用在静态内部类中定义的变量。
使用场景:和外部类联系紧密,但是并不依赖于外部类实例的情况下,可以考虑使用静态内部类。
三、非静态内部类
1. 成员内部类
测试代码如下:
public class Outer {
private String a = "a";
private static String b = "b";
public String c = "c";
public static String d = "d";
private static String e = "e";
private void method1() {
System.out.println("method1");
}
private static void method2() {
System.out.println("method2");
}
// 非静态内部类可以使用外部类的所有静态和非静态资源,但不可以自己定义静态资源(包括静态变量、静态方法和静态代码块)
public class Inner {
// 报错,因为成员内部类不能定义静态变量
// private static int e = 5;
private int e = 5;
// 该方法不可以用静态变量修饰
public void sayHello() {
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
method1();
method2();
// 内部类定义和外部类同名的变量时,会使用在内部类中定义的变量
System.out.println(e);
}
}
public static void main(String[] args) {
new Outer().new Inner().sayHello();
}
}
控制台输出如下:
a
b
c
d
method1
method2
5
结论:
- 成员内部类的调用方法:
new Outer().new Inner().sayHello()
- 成员内部类可以直接访问外部类的静态资源和非静态资源。
- 内部类定义和外部类同名的变量时,会使用在内部类中定义的变量。
使用场景:和外部类联系密切,并且高度依赖外部类实例的情况下,定义一个成员内部类是不错的选择。
2. 方法内部类
测试代码如下:
public class Outer {
private String name = "itming";
public void sayHello() {
class Inner {
public void showName() {
System.out.println("My name is " + name);
}
}
new Inner().showName();
}
public static void main(String[] args) {
new Outer().sayHello();
}
}
控制台输出如下:
My name is itming
结论:
- 方法内部类的生命周期不超过包含它的方法的生命周期,因此,方法内部类只能在方法中使用。
- 由于方法内部类只能在包含它的方法内部使用,所以访问修饰符没有任何意义,于是 Java 直接禁止对方法内部类使用访问修饰符,如果使用的话会编译报错。
使用场景:一般只在需要高度封装的时候才会将类定义成方法内部类。
3. 匿名内部类
测试代码如下:
public class Outer {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("Hello Thread!");
}
}
}.start();
new Thread(() -> {
for (int i = 0; i < 3; i++) {
System.out.println("Hello Lambda!");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("Hello Runnable!");
}
}
}).start();
}
}
控制台输出如下:
Hello Thread!
Hello Thread!
Hello Thread!
Hello Lambda!
Hello Lambda!
Hello Lambda!
Hello Runnable!
Hello Runnable!
Hello Runnable!
使用场景:对代码简洁度有要求的情况下首选匿名内部类。