-
概念
1. 在类的内部再定义一个完整的类称为内部类。
2. 内部类编译之后会生成独立的字节码文件。
3. 内部类可以访问外部类的私有成员,而不破坏封装。
4. 可为外部类提供必要的内部功能组件。 -
成员内部类
1.成员内部类:是外部类的一个成员部分,创建内部类时,必须依赖外部类
2.示例:
public class Student {
private int age = 18;
private String name = "张三";
public void end(){
XinXi xinXi = new XinXi();
System.out.println("外部类的方法:姓名:" + name + "\t年龄:" + xinXi.age);
}
// 定义一个成员内部类
public class XinXi{
private int age = 20;
public void getXinxi(){
// 内部类可以直接访问外部类的属性,如果和外部类的属性名重复时,通过类名.this.属性名访问
System.out.println("内部类的方法:姓名:" + name + "\t年龄:" + Student.this.age);
// 访问外部类的方法
end();
}
}
}
测试使用
@Test
public void test01(){
// 其他类使用成员内部类 创建对象的方式
Student student = new Student();
Student.XinXi xinXi = student.new XinXi();
xinXi.getXinxi();
}
输出结果:
内部类的方法:姓名:张三 年龄:18
外部类的方法:姓名:张三 年龄:20
3.小结:
内部类可以直接访问外部类的属性/方法,如果和外部类的属性名重复时,通过 外部类名.this.属性名/方法 访问。
成员内部类中不能声明静态属性
可以是任何的访问修饰符
内部类也是类,继承、重写、重载、this、super等都可以用
外部类访问内部类必须先new 内部类对象
内部类可以直接使用外部类的任何信息
- 静态内部类
1.不依赖外部类对象,可直接创建内部类对象,或通过类名访问静态成员
2.只能访问外部类的静态成员(外部类实例成员需要创建对象)
3.示例:
public class Student {
private int age = 18;
private String name = "张三";
private static String department = "BD29"; // 部门
public void end(){
XinXi xinXi = new XinXi();
System.out.println("外部类的方法:姓名:" + name + "\t年龄:" + xinXi.age);
}
// 静态内部类
public static class Xinxi02{
private int age = 3;
public void getXinxi02(){
System.out.println("静态内部类的非静态方法:部门:" + department);
}
public static void print(){
System.out.println("静态内部类的静态方法:部门:" + department);
}
}
}
测试使用
@Test
public void test02(){
// 访问内部类的静态信息可以直接访问:外部类名.内部类名.静态信息
Student.Xinxi02.print();
// 创建对象,访问非静态方法
Student.Xinxi02 xinxi02 = new Student.Xinxi02();
xinxi02.getXinxi02();
}
输出结果:
静态内部类的静态方法:部门:BD29
静态内部类的非静态方法:部门:BD29
4.小结:
内部类可以包含任意的信息
静态内部类的方法只能访问外部类的静态信息
访问内部类的静态信息可以直接访问:外部类名.内部类名.静态信息
静态内部类可以独立存在,不依赖于外部类
创建静态内部类对象 :外部类.内部类 引用 = new 外部类.内部类();
- 局部内部类
1.定义在方法内部的类,作用范围和创建对象的范围仅在方法主体中,隐藏类的实现细节.
2.局部内部类访问外部类的局部变量,无法保证对象和局部变量的声明周期一致。必须添加final前缀,保证局部变量的生命周期大于对象的声明周期。(JDK8之后可以省略 final)
3.隐藏类的实现细节
4.示例:
public class Student {
private int age = 18;
private String name = "张三";
private static String department = "BD29"; // 部门
public void end(){
XinXi xinXi = new XinXi();
System.out.println("外部类的方法:姓名:" + name + "\t年龄:" + xinXi.age);
}
// 方法内部定义一个Xinxi03的类
public void localClass(){
String sex = "男";
// 局部内部类,不能有访问修饰符
class Xinxi03{
// 可以随意访问外部类的任何信息、可以直接访问方法内的局部变量和参数(JDK8及以后)但不能更改
public void print(){
System.out.println("姓名:" + name + "\t性别:" + sex);
// 不能修改
//sex = "女";
}
}
// 局部内部类只能在方法内部使用
Xinxi03 xinxi03 = new Xinxi03();
xinxi03.print();
}
}
测试使用
@Test
public void test03(){
Student student = new Student();
student.localClass();
}
输出结果:
姓名:张三 性别:男
5.小结:
类不能有访问修饰符。
仅在方法内使用。
无法声明静态信息
可以直接访问方法内的局部变量和参数(JDK8新特性),但不能更改。
可以随意访问外部类的任何信息。
- 匿名内部类(重要)
1.没有类名的局部内部类。
2.必须继承一个父类或是实现一个接口。
3.定义类、实现类、创建对象的语法合并。
4.仅父类或接口公开,实现类作为匿名内部类加以隐藏,强制弱耦合。
5.匿名内部类没有访问修饰符
6.使用匿名内部类时,这个new之后的类首先是要存在的,其次我们是要重写new之后的类的某个或某些方法。
7.匿名内部类没有构造方法
8.匿名内部类访问方法参数时也和局部内部类同样有限制。
代码示例:
public class Student {
public void anonymous(){
// 当需要创建接口对象的实现类时,可以通过匿名内部类快速创建
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("启动了一个❤线程");
}
}).start();
}
}
测试使用
@Test
public void test04(){
Student student = new Student();
student.anonymous();
}
输出结果:启动了一个❤线程