17. 内部类
在Java中,内部类是定义在另一个类或者代码块内部的类。内部类提供了一种将逻辑相关的类组织在一起的方式,同时可以隐藏它们的实现细节。
成员内部类可以分为:
- 成员内部类: 定义在类内部的普通内部类,可以访问外部类的所有成员。
- 静态内部类: 使用 static 修饰的内部类,与外部类的对象实例无关。
- 方法内部类: 定义在方法内部的内部类,只能在该方法内使用。
- 匿名内部类: 没有类名的内部类,通常用于创建只需使用一次的类实例。
内部类具有以下特点:
- 可以访问外部类的所有成员,包括私有成员。
- 可以实现更好的封装,将相关类组织在一起,降低了代码的复杂度。
- 内部类可以实现接口,使得外部类的实例拥有多个接口的特性。
内部类的使用场景:
- 当一个类仅在一个类内部使用时,可以考虑使用内部类,以避免对外暴露不必要的类。
- 在事件处理或者回调函数中,匿名内部类可以很方便地实现接口或抽象类的方法。
17.1 成员内部类
// 外部类
public class Outer {
private int m = 0;
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
public void test1() {
System.out.println("外部类Outer的方法test1");
}
// 成员内部类
class Inner {
private int n = 1;
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
public void show1() {
System.out.println("内部类Inner的方法show1");
test1();
System.out.println("内部类Inner调用外部类m=" + getM());
}
public void show2() {
System.out.println("内部类Inner的方法show2");
}
}
public void test2() {
System.out.println("外部类Outer方法test2");
Inner inner = new Inner();
System.out.println("内部类的成员变量n=" + inner.getN());
inner.show2();
}
}
class Example {
public static void main(String[] args) {
Outer outer = new Outer(); // 实例化外部类对象
Outer.Inner inner = outer.new Inner(); // 实例化内部类对象
inner.show1();
outer.test2();
}
}
/*
内部类Inner的方法show1
外部类Outer的方法test1
内部类Inner调用外部类m=1
外部类Outer方法test2
内部类的成员变量n=1
内部类Inner的方法show2
*/
17.2 方法内部类
// 外部类
public class Outer {
private int m = 10;
public void test1() {
System.out.println("外部类Outer的方法test1");
}
public void test2() {
System.out.println("外部类Outer方法test2");
// 方法内部类
class Inner {
private int n = 1;
public void show() {
System.out.println("内部类Inner调用外部类m=" + m);
test1();
}
}
Inner inner = new Inner();
System.out.println("方法内部类变量n=" + inner.n);
inner.show();
}
}
class Example {
public static void main(String[] args) {
Outer outer = new Outer();
outer.test2();
}
}
/*
外部类Outer方法test2
方法内部类变量n=1
内部类Inner调用外部类m=10
外部类Outer的方法test1
*/
17.3 静态内部类
package demo3;
public class Outer {
private static int m = 10;
// 静态内部类
static class Inner {
private int n = 1;
public void show() {
System.out.println("Inner的show方法可以调用Outer的属性m=" + m);
}
}
public void test() {
System.out.println();
Inner inner = new Inner();
System.out.println("Outer类方法test可以调用Inner的属性n=" + inner.n);
}
}
package demo3;
public class OuterTest {
public static void main(String[] args) {
Outer outer = new Outer();
outer.test(); // Outer类方法test可以调用Inner的属性n=1
// 创建内部类对象
Outer.Inner inner = new Outer.Inner();
inner.show(); // Inner的show方法可以调用Outer的属性m=10
}
}
17.4 匿名内部类
匿名内部类是没有名称的内部类。在java中调用某个方法时,如果该方法的参数是接口类型,除了可以传入一个接口实现类外,还可以使用实现接口的匿名内部类作为参数,在匿名内部类中直接完成方法的实现。
// 1. 使用接口作为匿名内部类
package demo4;
public interface Animal {
void shout(); // 动物发出叫声方法
}
package demo4;
public class AnimalTest {
public static void main(String[] args) {
String name = "旺财";
// 定义一个匿名内部类是Animal接口的实现类
Animal an = new Animal() {
@Override
public void shout() {
System.out.println(name + "汪汪....");
}
};
an.shout(); // 旺财汪汪....
}
}
// 接口类型的参数接收一个匿名内部类对象
package demo4;
public class AnimalTest1 {
public static void animalShout(Animal an) {
an.shout();
}
public static void main(String[] args) {
animalShout(new Animal() {
@Override
public void shout() {
System.out.println("汪汪....");
}
}); // 汪汪....
animalShout(new Animal() {
@Override
public void shout() {
System.out.println("喵喵....");
}
}); // 喵喵....
animalShout(new Animal() {
@Override
public void shout() {
System.out.println("咕咕....");
}
}); // 咕咕....
}
}
// 2. 普通类使用匿名对象
package demo4;
public class Dog {
private String name;
public Dog() {
}
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void play() {
System.out.println(getName() + "在玩耍");
}
public void eat(