Java内部类的4种用法详解(附带实例)
在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
根据内部类的位置、修饰符和定义的方式,Java 程序里可以将内部类分为四种,分别是成员内部类、局部内部类、静态内部类和匿名内部类。
内部类有三个共性:
同时,若要在外部类外访问内部类,则需要外部类对象去创建内部类对象,在外部类外创建内部类对象的语法格式如下。
【实例】定义一个外部类 Grade 和一个成员内部类,通过测试类测试外部类和内部类的使用原则。
局部内部类在方法外是无法访问到的,但它的实例可以从方法中返回,并且实例在不再被引用之前会一直存在。
局部内部类也可以访问所在方法的局部变量、方法参数等,限制是局部变量或方法参数只有在声明为 final 时才能被访问。
【实例】定义外部类 TestInnerClass1 和内部类 MInner,并测试外部类和内部类相互访问的原则。
静态内部类可以定义实例成员和静态成员,可以直接访问外部类的静态成员,但如果要访问外部类的实例成员,必须通过外部类对象访问。
另外,如果在外部类外访问静态内部类成员,则不需要创建外部类对象,只需要创建内部类对象即可。
【实例】定义类 Outter,并在其内部定义静态类 Inner,在测试类 TestStaticInner 中测试访问静态内部类的原则。
匿名内部类的语法格式如下:
【实例】定义抽象类 Bird,在测试类 TestAnonyClass 中定义匿名类实现 Bird 类,重写 Bird 类中的抽象方法。
在使用匿名内部类的过程中,应注意以下几点:
根据内部类的位置、修饰符和定义的方式,Java 程序里可以将内部类分为四种,分别是成员内部类、局部内部类、静态内部类和匿名内部类。
内部类有三个共性:
- 内部类与外部类经 Java 编译器编译后生成的两个类是独立的;
- 内部类是外部类的一个成员,因此能访问外部类的任何成员(包括私有成员),但外部类不能直接访问内部类成员;
- 内部类可为静态,可用 protected 和 private 修饰。
Java成员内部类
成员内部类可以看成是外部类的一个成员,能直接访问外部类的所有成员,但在外部类中访问内部类,则需要在外部类中创建内部类的对象,使用内部类的对象访问内部类的成员。同时,若要在外部类外访问内部类,则需要外部类对象去创建内部类对象,在外部类外创建内部类对象的语法格式如下。
外部类名.内部类名 引用变量名 = new 外部类名().new 内部类名();下面通过一个例子演示成员内部类的使用原则。
【实例】定义一个外部类 Grade 和一个成员内部类,通过测试类测试外部类和内部类的使用原则。
class Grade {
private int count;
class Student {
private String name;
Student(String name) {
this.name = name;
}
public void addGrage() {
count++;
}
}
public void add() {
Student s = new Student("John");
s.addGrage(); // 在外部类内使用内部类成员,需要通过创建内部类对象来访问
System.out.println("欢迎 " + s.name + " 加入班级!目前班级人数:" + count);
}
}
public class TestInnerClass {
public static void main(String[] args) {
Grade g = new Grade();
// 在外部类外使用内部类
Grade.Student john = g.new Student("John");
g.add();
}
}
运行该程序,结果为:
欢迎 John 加入班级!目前班级人数:1
Java局部内部类
局部内部类的使用和成员内部类的使用基本一致,只是局部内部类定义在外部类的方法中,就像局部变量一样,并不是外部类的成员。局部内部类在方法外是无法访问到的,但它的实例可以从方法中返回,并且实例在不再被引用之前会一直存在。
局部内部类也可以访问所在方法的局部变量、方法参数等,限制是局部变量或方法参数只有在声明为 final 时才能被访问。
【实例】定义外部类 TestInnerClass1 和内部类 MInner,并测试外部类和内部类相互访问的原则。
public class TestInnerClass1 {
public void show() { // 外部类中的方法
final int a = 20;
int b = 15;
// 方法内部类
class MInner {
int c = 2; // 内部类中的变量
public void print() {
System.out.println("访问外部类的方法中的常量 a:" + a);
System.out.println("访问内部类中的变量 c:" + c);
}
}
MInner mi = new MInner(); // 创建方法内部类的对象
mi.print(); // 调用内部类的方法
}
public static void main(String[] args) {
TestInnerClass1 test = new TestInnerClass1(); // 创建外部类的对象
test.show(); // 调用外部类的方法
}
}
程序的执行结果如下:
访问外部类的方法中的常量 a:20
访问内部类中的变量 c:2
Java静态内部类
如果不需要外部类对象与内部类对象之间有联系,可以将内部类声明为 static,称为静态内部类。静态内部类可以定义实例成员和静态成员,可以直接访问外部类的静态成员,但如果要访问外部类的实例成员,必须通过外部类对象访问。
另外,如果在外部类外访问静态内部类成员,则不需要创建外部类对象,只需要创建内部类对象即可。
【实例】定义类 Outter,并在其内部定义静态类 Inner,在测试类 TestStaticInner 中测试访问静态内部类的原则。
class Outer {
// 定义类静态成员
private static String name = "Outter";
private static int id;
// 定义静态内部类
public static class Inner {
public static String name = "Outter.inner";
public void print() {
System.out.print(Outter.name);
System.out.println(":" + id);
}
}
}
public class TestStaticInner {
public static void main(String[] args) {
// 访问静态内部类的静态成员
String s = Outter.Inner.name;
System.out.println(s);
// 创建静态内部类对象
Outter.Inner inner = new Outter.Inner();
inner.print();
}
}
运行程序,结果为:
Outter.inner
Outter:0
Java匿名内部类
如果某个类的实例只使用一次,则可以将类的定义与类对象的创建,放到一起完成,或者说在定义类的同时就创建一个类对象。匿名内部类的语法格式如下:
new className(){
//匿名内部类的类体
}
这种形式的 new 语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口。它还创建那个类的一个新实例,并把它作为语句的结果而返回。要扩展的类和要实现的接口是 new 语句的操作数,后跟匿名类的主体。【实例】定义抽象类 Bird,在测试类 TestAnonyClass 中定义匿名类实现 Bird 类,重写 Bird 类中的抽象方法。
abstract class Bird {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract int fly();
}
public class TestAnonyClass {
public void test(Bird bird) {
System.out.println(bird.getName() + " 能够飞 " + bird.fly() + " 米");
}
public static void main(String[] args) {
TestAnonyClass test = new TestAnonyClass();
test.test(new Bird() { // 匿名内部类
public int fly() {
return 10000;
}
public String getName() {
return "大雁";
}
});
}
}
程序运行结果为:
大雁 能够飞 10000 米
在 TestAnonyClass 类中,test() 方法接收一个 Bird 类型的参数,同时我们知道一个抽象类是没有办法直接 new 的,所以在 main() 方法中直接使用匿名内部类来创建一个 Bird 实例。在使用匿名内部类的过程中,应注意以下几点:
- 使用匿名内部类时,必须是继承一个类或者实现一个接口,但是两者不可兼得;
- 匿名内部类中是不能定义构造函数的;
- 匿名内部类中不能存在任何的静态成员变量和静态方法;
- 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效;
- 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
ICP备案:
公安联网备案: