文章目录
零、本讲学习目标
1、掌握成员内部类的使用
2、掌握局部内部类的使用
3、掌握静态内部类的使用
4、掌握匿名内部类的使用
一、内部类概述
在Java中,允许在一个类的内部定义类,这样的类称作内部类(inner class),这个内部类所在的类称作外部类(outer class)。
二、成员内部类(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 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
+ “工作。”);
(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();
}
}
课堂练习:在外部类Scool里添加成员内部类Student
- 成员内部类Student包含name与age属性
- 成员内部类Student包含learn()方法,访问外部类School成员
- 外部类School添加test2()方法,访问成员内部类Student的成员
- 在测试类TestSchool里添加对成员内部类Student的测试代码
三、局部内部类(Local Inner Class)
1、局部内部类定义
局部内部类,也叫做方法内部类,就是定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,其有效范围只限于方法内部。
2、局部内部类说明
在局部内部类中,局部内部类可以访问外部类的所有成员变量和方法,而局部内部类中的变量和方法却只能在创建该局部内部类的方法中进行访问。
3、局部内部类案例演示
(1)创建School类,在test()方法里创建局部内部类Teacher
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
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();
}
}
运行程序,查看效果:
但是要注意,只有创建了局部内部类的方法才能访问局部内部类对象的成员变量和方法,外部类甚至是无法访问局部内部类对象的,因为局部内部类只是在创建它的成员方法里有效,一旦越出创建局部内部类的方法,局部内部类就失效了。
四、静态内部类(Static Inner Class)
1、静态内部类定义
所谓静态内部类,就是使用static关键字修饰的成员内部类。
2、静态内部类说明
静态内部类在成员内部类前增加了static关键字,在功能上,静态内部类中只能访问外部类的静态成员,同时通过外部类访问静态内部类成员时,可以跳过外部类从而直接通过内部类访问静态内部类成员。
3、创建静态内部类对象的语法格式
外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();
4、静态内部类案例演示
(1)创建School类,包含静态内部类Teacher
package net.hw.lesson16.static_;
/**
* 功能:演示静态内部类
* 作者:华卫
* 日期:2020年05月13日
*/
public class School {
// 定义外部类静态成员变量
static String name = "泸州职业技术学院";
// 定义外部类静态成员方法
public static void speak() {
System.out.println("欢迎参观" + name);
}
// 定义静态内部类
public static class Teacher {
private static String name = "李晓红";
private static int age = 30;
// 定义静态内部类方法,访问外部类静态成员变量与方法
public void work() {
// 访问外部类静态成员方法
speak();
// 访问外部类静态成员变量
System.out.println("我在" + School.name + "工作。");
}
// 定义静态内部类静态方法
public static void speak() {
System.out.println("我叫" + name + ",今年" + age + "岁了。");
}
}
// 定义外部类方法
public void test() {
// 访问静态内部类的静态成员变量
System.out.println(Teacher.name + " : " + Teacher.age);
// 通过静态内部类名访问静态内部类的静态成员方法
Teacher.speak();
// 不能静态内部类名访问静态内部类的非静态成员方法
// Teacher.work(); // 程序编译要报错
}
}
(2)创建测试类TestSchool
package net.hw.lesson16.static_;
/**
* 功能:测试School类
* 作者:华卫
* 日期:2020年05月13日
*/
public class TestSchool {
public static void main(String[] args) {
// 调用外部类的静态成员方法
School.speak();
// 调用外部类的非静态成员方法
new School().test();
// 基于外部类创建静态内部类对象
School.Teacher teacher = new School.Teacher();
// 调用静态内部类对象的非静态成员方法
teacher.work();
// 调用静态内部类对象的静态成员方法
teacher.speak();
}
}
运行程序,查看结果:
说明:外部类School成员方法test()不能通过静态内部类名访问其非静态成员方法work():
当然实例化静态内部类之后,就可以访问静态内部类的非静态成员方法work():
五、匿名内部类(Anonymous Inner Class)
1、匿名内部类定义
匿名内部类其实就是没有名称的内部类。
2、匿名内部类说明
在调用包含有接口类型参数的方法时,通常为了简化代码,可以直接通过匿名内部类的形式传入一个接口类型参数,在匿名内部类中直接完成方法的实现。
3、访问局部变量注意事项
从JDK 8开始,允许在局部内部类、匿名内部类中访问非final修饰的局部变量,而在JDK 8之前,局部变量前必须加final修饰符,否则程序编译报错。
4、创建匿名内部类对象的语法格式
new 父接口(){ // 匿名内部类实现部分 }
5、匿名内部类案例演示
(1)创建动物接口Animal,包含eat()抽象方法
package net.hw.lesson16.anonymous;
/**
* 功能:动物接口
* 作者:华卫
* 日期:2020年05月13日
*/
public interface Animal {
void eat();
}
(2)创建Student类,包含喂养方法feed(Animal animal)
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
package net.hw.lesson16.anonymous;
/**
* 功能:测试Student类
* 作者:华卫
* 日期:2020年05月13日
*/
public class TestStudent {
public static void main(String[] args) {
// 实例化对象
Student student = new Student();
// 设置对象属性
student.setName("李晓红");
// 定义动物名(非final局部变量)
String animalName = "瑞瑞";
// 调用对象方法(定义匿名内部类对象作为参数传给feed()方法)
student.feed(new Animal() {
@Override
public void eat() {
// JDK1.8开始,局部内部类与匿名内部类可以访问非final局部变量
System.out.println("狗崽[" + animalName + "]爱啃骨头。" );
}
});
}
}
运行程序,查看结果:
六、课后作业
1、创建Car接口
2、创建Driver类
3、创建测试类TestDriver
基于Car接口创建匿名内部类对象作为参数传给驾驶员对象的drive()方法。