Java讲课笔记16:内部类

文章目录

  • 零、本讲学习目标
    • 1、掌握成员内部类的使用
    • 2、掌握局部内部类的使用
    • 3、掌握静态内部类的使用
    • 4、掌握匿名内部类的使用
  • 一、内部类概述
  • 二、成员内部类(Member Inner Class)
    • 1、成员内部类定义
    • 2、成员内部类说明
    • 3、创建内部类对象的语法格式
    • 4、成员内部类案例演示
      • (1)创建School类,包含内部类Teacher
      • (2)创建测试类TestSchool
    • 课堂练习:在外部类Scool里添加成员内部类Student
  • 三、局部内部类(Local Inner Class)
    • 1、局部内部类定义
    • 2、局部内部类说明
    • 3、局部内部类案例演示
      • (1)创建School类,在test()方法里创建局部内部类Teacher
      • (2)创建测试类TestSchool
  • 四、静态内部类(Static Inner Class)
    • 1、静态内部类定义
    • 2、静态内部类说明
    • 3、创建静态内部类对象的语法格式
    • 4、静态内部类案例演示
      • (1)创建School类,包含静态内部类President
      • (2)创建测试类TestSchool
  • 五、匿名内部类(Anonymous Inner Class)
    • 1、匿名内部类定义
    • 2、匿名内部类说明
    • 3、访问局部变量注意事项
    • 4、创建匿名内部类对象的语法格式
    • 5、匿名内部类案例演示
      • (1)创建动物接口Animal,包含eat()抽象方法
      • (2)创建Student类,包含喂养方法feed(Animal animal)
      • (3)创建测试类TestStudent
      • (4)创建测试类TestStudent1
  • 六、课后作业
    • 1、创建Car接口
    • 2、创建Driver类
    • 3、创建测试类TestDriver
    • 4、演示程序运行效果

零、本讲学习目标

1、掌握成员内部类的使用

2、掌握局部内部类的使用

3、掌握静态内部类的使用

4、掌握匿名内部类的使用

一、内部类概述

在Java中,允许在一个类的内部定义类,这样的类称作内部类(inner class),这个内部类所在的类称作外部类(outer class)。
Java讲课笔记16:内部类_第1张图片

二、成员内部类(Member Inner Class)

1、成员内部类定义

在一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称作成员内部类。其实我们可以将内部类理解为国中之国。

2、成员内部类说明

在成员内部类中,可以访问外部类的所有成员,包括成员变量和成员方法;在外部类中,同样可以访问成员内部类的变量和方法。

3、创建内部类对象的语法格式

外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

4、成员内部类案例演示

(1)创建School类,包含内部类Teacher

在这里插入图片描述

package net.hw.lesson16.member;

/**
 * 功能:演示成员内部类
 * 作者:华卫
 * 日期:2020年05月12日
 */
public class School {
    // 定义外部类成员变量
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // 定义外部类成员方法
    public void speak() {
        System.out.println("欢迎参观" + name);
    }

    // 定义成员内部类
    class Teacher {
        // 定义成员内部类成员变量
        private String name;
        private int age;

        // 定义成员内部类成员方法
        public void work() {
            // 访问外部类成员方法
            speak();
            // 访问外部类成员变量
            System.out.println("我在" + School.this.name + "工作。");
        }
    }

    // 定义外部类成员方法,访问成员内部类成员变量与方法
    public void test() {
        // 创建成员内部类对象
        Teacher teacher = new Teacher();
        // 访问成员内部类成员变量
        teacher.name = "李晓红";
        teacher.age = 20;
        System.out.println("我叫" + teacher.name + ",今年" + teacher.age + "岁了。");
        // 访问成员内部类成员方法
        teacher.work();
    }
}

说明:内部类要访问外部类同名变量,采用外部类名.this.外部类同名变量,比如第35行代码:System.out.println(“我在” + School.this.name + “工作。”); 当然也可以使用new School().name方式来访问外部类成员变量。

(2)创建测试类TestSchool

在这里插入图片描述

package net.hw.lesson16.member;

/**
 * 功能:测试School类
 * 作者:华卫
 * 日期:2020年05月12日
 */
public class TestSchool {
    public static void main(String[] args) {
        // 创建外部类对象
        School school = new School();
        // 设置外部类对象属性
        school.setName("泸州职业技术学院");
        // 基于外部类对象创建成员内部类对象
        School.Teacher teacher = school.new Teacher();
        // 调用成员内部类对象的成员方法(访问外部类成员变量与方法)
        teacher.work();
        // 调用外部类对象的成员方法(访问成员内部类成员变量与方法)
        school.test();
    }
}

Java讲课笔记16:内部类_第2张图片

课堂练习:在外部类Scool里添加成员内部类Student

  • 成员内部类Student包含name与age属性
  • 成员内部类Student包含learn()方法,访问外部类School成员
  • 外部类School添加test2()方法,访问成员内部类Student的成员
  • 在测试类TestSchool里添加对成员内部类Student的测试代码

三、局部内部类(Local Inner Class)

1、局部内部类定义

局部内部类,也叫做方法内部类,就是定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,其有效范围只限于方法内部。

2、局部内部类说明

在局部内部类中,局部内部类可以访问外部类的所有成员变量和方法,而局部内部类中的变量和方法却只能在创建该局部内部类的方法中进行访问。

3、局部内部类案例演示

(1)创建School类,在test()方法里创建局部内部类Teacher

Java讲课笔记16:内部类_第3张图片

package net.hw.lesson16.local;

/**
 * 功能:演示局部内部类
 * 作者:华卫
 * 日期:2020年05月12日
 */
public class School {
    // 定义外部类成员变量
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // 定义外部类成员方法
    public void speak() {
        System.out.println("欢迎参观" + name);
    }

    // 定义外部类成员方法,在里面定义局部内部类
    public void test() {
        // 定义局部内部类
        class Teacher {
            // 定义局部内部类成员变量
            private String name;
            private int age;

            // 定义局部内部类成员方法
            public void work() {
                // 访问外部类成员方法
                speak();
                // 访问外部类成员变量
                System.out.println("我在" + School.this.name + "工作。");
            }
        }

        // 在局部内部类所在方法里创建局部内部类对象
        Teacher teacher = new Teacher();
        // 访问局部内部类成员变量
        teacher.name = "李晓红";
        teacher.age = 20;
        System.out.println("我叫" + teacher.name + ",今年" + teacher.age + "岁了。");
        // 访问局部内部类成员方法
        teacher.work();
    }
}

在外部类School里定义了成员变量name、成员方法speak()与test(),并在test()里创建了局部内部类Teacher,然后在局部内部类Teacher里创建了work()方法来测试对外部类变量和方法的调用,同时,还在test()方法测试对局部内部类变量和方法的调用。

(2)创建测试类TestSchool

Java讲课笔记16:内部类_第4张图片

package net.hw.lesson16.local;

/**
 * 功能:测试School类
 * 作者:华卫
 * 日期:2020年05月12日
 */
public class TestSchool {
    public static void main(String[] args) {
        // 实例化外部类对象
        School school = new School();
        // 设置对象属性
        school.setName("泸州职业技术学院");
        // 调用外部类普通方法
        school.speak();
        // 通过外部类对象调用创建了局部内部类的方法
        school.test();
    }
}

运行程序,查看效果:
Java讲课笔记16:内部类_第5张图片
但是要注意,只有创建了局部内部类的方法才能访问局部内部类对象的成员变量和方法,外部类甚至是无法访问局部内部类对象的,因为局部内部类只是在创建它的成员方法里有效,一旦越出创建局部内部类的方法,局部内部类就失效了。
Java讲课笔记16:内部类_第6张图片

四、静态内部类(Static Inner Class)

1、静态内部类定义

所谓静态内部类,就是使用static关键字修饰的成员内部类。

2、静态内部类说明

静态内部类在成员内部类前增加了static关键字,在功能上,静态内部类中只能访问外部类的静态成员,同时通过外部类访问静态内部类成员时,可以跳过外部类从而直接通过内部类访问静态内部类成员。

3、创建静态内部类对象的语法格式

外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();

4、静态内部类案例演示

(1)创建School类,包含静态内部类President

Java讲课笔记16:内部类_第7张图片

package net.hw.lesson16.static_;

/**
 * 功能:演示静态内部类
 * 作者:华卫
 * 日期:2020年05月13日
 */
public class School {
    // 定义外部类静态成员变量
    static String name = "泸州职业技术学院";

    // 定义外部类静态成员方法
    public static void speak() {
        System.out.println("欢迎访问" + name);
    }

    // 定义静态内部类
    static class President {
        // 定义静态内部类静态成员变量
        private static String name = "杨宗伟";
        private static int age = 56;

        // 定义静态内部类成员方法
        public void work() {
            // 访问外部类静态成员方法
            speak();
            // 访问外部类静态成员变量
            System.out.println("我在" + School.name + "工作。");
        }

        // 定义静态内部类静态成员方法
        public static void speak() {
            System.out.println("我是校长,叫" + name + ",今年" + age + "岁了。");
        }
    }

    // 定义外部类成员方法
    public void test() {
        // 访问静态内部类静态成员变量
        System.out.println("校长叫" + President.name + ",今年" + President.age + "岁了。");
        // 通过静态内部类对象去访问静态内部类成员方法
        new President().work();  // President.work() 编译要报错
        // 通过静态内部类去访问静态内部类静态成员方法
        President.speak();
    }
}

(2)创建测试类TestSchool

Java讲课笔记16:内部类_第8张图片

package net.hw.lesson16.static_;

/**
 * 功能:测试School类
 * 作者:华卫
 * 日期:2020年05月13日
 */
public class TestSchool {
    public static void main(String[] args) {
        // 访问外部类静态成员变量
        System.out.println("学校名称:" + School.name);
        // 通过外部类名访问静态成员方法
        School.speak();
        // 通过外部类对象访问非静态成员方法
        new School().test();
        // 基于外部类名创建静态内部类对象
        School.President president = new School.President();
        // 通过静态内部类对象访问非静态成员方法
        president.work();
        // 通过静态内部类对象访问静态成员方法
        president.speak();
        // 通过静态内部类名访问静态成员方法
        School.President.speak();
    }
}

运行程序,查看结果:
Java讲课笔记16:内部类_第9张图片
说明:外部类School成员方法test()不能通过静态内部类名访问其非静态成员方法work():
Java讲课笔记16:内部类_第10张图片

五、匿名内部类(Anonymous Inner Class)

1、匿名内部类定义

匿名内部类其实就是没有名称的内部类。

2、匿名内部类说明

在调用包含有接口类型参数的方法时,通常为了简化代码,可以直接通过匿名内部类的形式传入一个接口类型参数,在匿名内部类中直接完成方法的实现。

3、访问局部变量注意事项

从JDK 8开始,允许在局部内部类、匿名内部类中访问非final修饰的局部变量,而在JDK 8之前,局部变量前必须加final修饰符,否则程序编译报错。

4、创建匿名内部类对象的语法格式

new 父接口(){
    // 匿名内部类实现部分
}

5、匿名内部类案例演示

(1)创建动物接口Animal,包含eat()抽象方法

Java讲课笔记16:内部类_第11张图片

package net.hw.lesson16.anonymous;

/**
 * 功能:动物接口
 * 作者:华卫
 * 日期:2020年05月13日
 */
public interface Animal {
    void eat();
}

(2)创建Student类,包含喂养方法feed(Animal animal)

Java讲课笔记16:内部类_第12张图片

package net.hw.lesson16.anonymous;

/**
 * 功能:学生类
 * 作者:华卫
 * 日期:2020年05月13日
 */
public class Student {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void feed(Animal animal) {
        System.out.println(name + "喂养一只动物。");
        animal.eat();
    }
}

(3)创建测试类TestStudent

Java讲课笔记16:内部类_第13张图片

package net.hw.lesson16.anonymous;

import java.util.Scanner;

/**
 * 功能:测试Student类
 * 作者:华卫
 * 日期:2020年05月13日
 */
public class TestStudent {
    public static void main(String[] args) {
        // 声明变量
        String studentName, animalName;
        Scanner sc = new Scanner(System.in);
        
        // 输入部分
        System.out.print("学生姓名:");
        studentName = sc.next();
        System.out.print("动物昵称:");
        animalName = sc.next();
        
        // 创建学生对象
        Student student = new Student();
        // 设置学生对象属性
        student.setName(studentName);
        
        // 调用对象方法,创建匿名接口对象作为参数
        student.feed(new Animal() {
            @Override
            public void eat() {
                // JDK1.8开始,局部内部类与匿名内部类可以访问非final局部变量
                System.out.println("狗崽[" + animalName + "]在啃骨头。" );
            }
        });
    }
}

运行程序,查看结果:
Java讲课笔记16:内部类_第14张图片
创建匿名接口对象作为方法参数,在我们后面的学习与项目实训中会反复用到,请大家务必理解并掌握。

当然刚才完成的任务,也可以采用局部内部类来完成。

(4)创建测试类TestStudent1

Java讲课笔记16:内部类_第15张图片

package net.hw.lesson16.anonymous;

import java.util.Scanner;

/**
 * 功能:测试Student类
 *      采用局部内部类
 * 作者:华卫
 * 日期:2020年05月13日
 */
public class TestStudent1 {
    public static void main(String[] args) {
        // 声明变量
        String studentName, animalName;
        Scanner sc = new Scanner(System.in);

        // 输入部分
        System.out.print("学生姓名:");
        studentName = sc.next();
        System.out.print("动物昵称:");
        animalName = sc.next();

        // 创建学生对象
        Student student = new Student();
        // 设置学生对象属性
        student.setName(studentName);

        // 定义局部内部类,实现动物接口
        class Dog implements Animal {
            private String name;

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            @Override
            public void eat() {
                System.out.println("狗崽[" + name + "]在啃骨头。" );
            }
        }

        // 创建狗对象
        Dog dog = new Dog();
        // 设置狗对象属性
        dog.setName(animalName);
        // 调用学生对象喂养方法
        student.feed(dog);
    }
}
  • 运行程序,查看结果
    Java讲课笔记16:内部类_第16张图片

六、课后作业

1、创建Car接口

在这里插入图片描述

2、创建Driver类

Java讲课笔记16:内部类_第17张图片

3、创建测试类TestDriver

在这里插入图片描述
基于Car接口创建匿名内部类对象作为参数传给驾驶员对象的drive()方法。

4、演示程序运行效果

Java讲课笔记16:内部类_第18张图片

你可能感兴趣的:(Java程序设计基础)