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

posted @ 2022-10-21 22:03  Bingeone  阅读(21)  评论(0编辑  收藏  举报