首页 > 编程笔记 > Java笔记 阅读:18

Java内部类的4种用法详解(附带实例)

在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

根据内部类的位置、修饰符和定义的方式,Java 程序里可以将内部类分为四种,分别是成员内部类、局部内部类、静态内部类和匿名内部类。

内部类有三个共性:

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 实例。

在使用匿名内部类的过程中,应注意以下几点:

相关文章