本文已参与「新人创作礼」活动,一起开启掘金创作之路。
内部类
即定义在类内的类。在java中,可以在类的内部再定义一个完整的类。
- 内部类编译后,可以生成独立的字节码文件 .class
- 内部类可以直接访问外部类的私有成员,而不是破坏封装。
- 可为外部类提供必要的内部功能组件。
内部类的分类
内部类,按照定义的位置和修饰符不同,可以分为:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
成员内部类
概念:在类的内部定义,与实际变量、实际方法同级别的类。
使用
- 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。
- Outer outer = new Outer();
- Inner inner = outer.new.Innter();
特点
- 书写位置:与属性、方法平级别,且没有使用static修饰的类
- 访问权限:内部类可以任意的访问权限
- 成员内部类中,不能写静态属性、静态方法。
- 编译之后生成的字节码文件格式:外部类$内部类.class
- 实例化对象,需要借助外部类的对象完成。
示例代码
// OuterClass.class
package com.laity.basicSyntax.day5.clnnerClass.aMember;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day5.clnnerClass.aMember
* @date Date : 2021年11月30日 19:27
* @Description: 成员内部类
* <p>
* 访问权限:内部类是作为外部类的一个成员,访问权限可以为是任意权限。
* 类中的成员定义:成员内部类中,不允许定义静态的成员(静态属性,静态方法)
*/
public class OuterClass {
public String name;
// 内部类的定义
public class InnerClass {
public String name;
public void show(String name) {
System.out.println("参数name=" + name);
System.out.println("内部类属性name=" + this.name);
System.out.println("外部类属性name=" + OuterClass.this.name);
}
}
}
// Program.class
package com.laity.basicSyntax.day5.clnnerClass.aMember;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day5.clnnerClass.aMember
* @date Date : 2021年11月30日 19:27
* @Description:
*/
public class Program {
public static void main(String[] args) {
// 1.外部类对象实例化
OuterClass outerClass = new OuterClass();
// 2.访问外部类中的属性
outerClass.name = "outerClass";
// 3.实例化一个内部类的对象
OuterClass.InnerClass innerClass = outerClass.new InnerClass(); // 类型为OuterClass.InnerClass
// 4.访问内部类的属性
innerClass.name = "innerClass";
// 5.调用内部类的方法
innerClass.show("parameter");
}
}
// 输出结果
参数name=parameter
内部类属性name=innerClass
外部类属性name=outerClass
静态内部类
**概念:**在类的内部定义,与实例变量、实例方法同级别的,使用static修饰的类。
**使用:**不依赖外部对象,可以直接创建或通过类名访问。
Outer.Inner inner = new Outer.Inner();
特点
- 书写位置:与属性、方法平级别,且使用关键字 static 修饰的类
- 访问权限:内部类可以任意的访问权限
- 静态内部类中,可以写静态属性、静态方法、属性、方法、构造方法。。。
- 编译之后生成的字节码文件格式:外部类$ 内部类.class
- 实例化对象,不需要借助外部类的对象完成。
示例代码
// OuterClass.class
package com.laity.basicSyntax.day5.clnnerClass.bStatic;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day5.clnnerClass.bStatic
* @date Date : 2021年11月30日 19:57
* @Description: 静态内部类
*/
public class OuterClass {
public String name;
public static String name1;
/**
* 静态内部类
*/
public static class InnerClass {
// 非静态的属性
public String name;
// 静态的属性
public static int age;
// 方法
public void show(String name){
System.out.println("参数name = "+name);
System.out.println("内部类的属性name = "+this.name);
System.out.println("外部类的属性name = "+"是访问不到的");
System.out.println("外部类的静态属性name1 = "+ OuterClass.name1);
}
}
}
// Program.class
package com.laity.basicSyntax.day5.clnnerClass.bStatic;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day5.clnnerClass.bStatic
* @date Date : 2021年11月30日 20:06
* @Description:
*/
public class Program {
public static void main(String[] args) {
// 实例化内部类对象
OuterClass.InnerClass innerClass = new OuterClass.InnerClass(); // 不需要外部类对象
// 成员访问
OuterClass.name1 = "outerClass";
innerClass.name = "innerClass";
innerClass.show("parameter");
}
}
// 运行打印结果
参数name = parameter
内部类的属性name = innerClass
外部类的属性name = 是访问不到的
外部类的静态属性name1 = outerClass
局部内部类
**概念:**是定义在外部类的方法中,作用范围和创建对象范围仅限于当前方法。(与成员内部类、静态内部类都不太一样)
特点
- 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final。
- 不能使用访问权限修饰符修饰。
- 书写位置:书写在一个类的方法内部,作用域仅限于当前方法。
- 局部内部类,编译后生成的字节码文件格式:外部类$ 序号 内部类名.class
实例代码
// Program.class
package com.laity.basicSyntax.day5.clnnerClass.cLocal;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day5.clnnerClass.cLocal
* @date Date : 2021年11月30日 20:48
* @Description: 局部内部类
*/
public class Program {
public static void main(String[] args) {
innerClassTest();
}
public static void innerClassTest() {
// 定义一个变量
// 如果在一个局部内部类中,使用到了局部变量,那么这个局部变量默认会被定义为 final
int a = 10;
/**
* 局部内部类
* 访问权限:什么权限都没有,都不可以写
*/
class InnerClass {
public String name;
public int age;
// 构造方法
public InnerClass() {
}
public void show() {
System.out.println("局部内部类的show方法");
System.out.println("a=" + a);
}
}
// a = 20;
// 对象实例化
InnerClass innerClass = new InnerClass();
innerClass.show();
}
}
匿名内部类
**概念:**没有类名的局部内部类
特点
- 一切特征与局部内部类相同。
- 必须继承一个父类或者实现一个接口。
- 定义类、实现类、创建对象的语法合并,只能创建一个改类的对象。
示例代码
package com.laity.basicSyntax.day5.clnnerClass.dAnonymous;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day5.clnnerClass.dAnonymous
* @date Date : 2021年11月30日 21:07
* @Description: 匿名内部类
*/
public class Program {
public static void main(String[] args) {
// 实例化一个对象
// 这就是一个匿名内部类
// 其实,这里实例化的是Person类的一个匿名子类的对象,并实现了向上转型。
Person laity = new Person() {
// 匿名内部的类体--->是Person的子类对象
@Override
public void walk() {
// 可以看成Override没有报错
System.out.println("我是laity");
super.walk(); // 调用父类的方法
}
};
// 方法调用
laity.walk();
}
}
// 定义一个方法
class Person {
public void walk(){
System.out.println("Person中的walk");
}
}