javaSE基础-内部类
内部类
定义:一个类A定义在类B中,则类A为内部类,类B为外部类
分类:
成员内部类
- 静态成员内部类
- 非静态成员内部类
局部内部类
- 方法内
- 代码块内
- 构造器内
示例一:
//InnerClassTest.java
/**
* 内部类<br>
* 1、定义:一个类A定义在类B中,则类A为内部类,类B为外部类<br>
* 2、分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)<br>
* 3、成员内部类:<br>
* <span>3.1、作为外部类的成员:<br>
* <span><span>a、调用外部结构<br>
* <span><span>b、可以被static修饰<br>
* <span><span>c、可以被被4种不同权限修饰<br>
*
* <span>3.2、作为一个类:<br>
* <span><span>a、类内部可以定义属性、方法、构造器等<br>
* <span><span>b、可以被final修饰,表示此类不能被继承<br>
* <span><span>c、可以被abstract修饰<br>
*
* @author jb
* @date 2022/08/07
*/
public class InnerClassTest {
public static void main(String[] args) {
// 创建成员内部类Dog实例(静态的)
Person.Dog dog = new Person.Dog();
dog.show();
// 创建成员内部类Bird实例(非静态的)
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
System.out.println("*************");
bird.dispaly("args");
}
}
class Person {
private String name = "张三";
private Integer age = 18;
public void run() {
System.out.println("Person is running...");
}
// 静态成员内部类
static class Dog {
private String name;
private Integer age;
public void show() {
System.out.println("The Dog is Kala.");
}
}
// 非静态成员内部类
final class Bird {
private String name = "麻雀";
public Bird() {
System.out.println("this is a bird");
}
public void sing() {
System.out.println("bird is singing。。。");
Person.this.run(); // 调用外部类方法的完整写法
System.out.println(age);// 外部类的成员变量
}
public void dispaly(String name) {
System.out.println(name);// 形参的变量 -> args
System.out.println(this.name);// 局部变量 -> 麻雀
System.out.println(Person.this.name);// 外部类的成员变量 -> 张三
}
}
public void method() {
// 局部内部类 -> 方法内
class AA {
}
}
public Person() {
// 局部内部类 -> 构造器内
class BB {
}
}
{
// 局部内部类 -> 代码块内
class CC {
}
}
}
使用问题
1、如何实例化成员内部类的对象:
// 创建成员内部类Dog实例(静态的)
Person.Dog dog = new Person.Dog();
dog.show();
// 创建成员内部类Bird实例(非静态的)
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
静态内部类实例化对象格式:
外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()
非静态内部类实例化对象格式:
外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()
2、如何在成员内部类中区别调用外部类的结构:
在内部类的方法内,针对有相同名的变量:
如:name在外部类成员变量、内部类局部变量、方法的形参变量都同时存在的调用方式:
class Person {
private String name = "张三";
private Integer age = 18;
...
// 非静态成员内部类
final class Bird {
private String name = "麻雀";
public Bird() {
System.out.println("this is a bird");
}
public void sing() {
System.out.println("bird is singing。。。");
Person.this.run(); // 调用外部类方法的完整写法
System.out.println(age);// 外部类的成员变量
}
public void dispaly(String name) {
System.out.println(name);// 形参的变量 -> args
System.out.println(this.name);// 局部变量 -> 麻雀
System.out.println(Person.this.name);// 外部类的成员变量 -> 张三
}
}
}
3、开发中局部内部类的一般使用方式:
示例二:
//InnerClassTest2.java
/**
* @author jb
* @date 2022/08/07
*/
public class InnerClassTest2 {
public Comparable getComparable() {
// 方式一:标准的局部内部类定义
class MyComparable implements Comparable {
@Override
public int compareTo(Object o) {
return 0;
}
}
return new MyComparable();
// 方式二:直接返回Comparable接口的一个匿名实现类
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}
成员内部类被类继承的使用方式:
示例三:
class WithInner {
class Inner{
}
}
class InheritInner extends WithInner.Inner {
// InheritInner() 是不能通过编译的,一定要加上形参
InheritInner(WithInner wi) {
wi.super(); //必须有这句调用
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner obj = new InheritInner(wi);
}
}
- 成员内部类的引用方式必须为 Outter.Inner,如:WithInner.Inner
- 构造器形参必须指向外部类对象的引用,并通过这个引用调用super(),如:wi.super();
局部内部类的方法中使用局部变量的注意
在局部内部类的方法调用局部内部类的局部变量,要求此变量必须声明为final
- Jdk7及之前的版本:要求此局部变量是显式的声明为final
- Jdk8及之后的版本:可以省略final声明
示例四:局部内部类
public class InnerClassTest{
public void method(){
//局部变量-- jdk7
//final int num = 10;
//局部变量-- jdk8
int num = 10;
class AA{
public void show(){
//num = 20; 此处无法覆盖num值,原因是num声明为final
System.out.println(num);
}
}
}
}
示例五:自定义异常类
public class MyException extends RuntimeException{
static final long serialVersionUID = -7034897193246938L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
总结:
成员内部类和局部内部类,在编译之后,生成字节码文件
格式:成员内部类:外部类$内部类名.class
局部内部类:外部类$数字 内部类名.class