JAVA基础--内部类

JAVA基础--内部类

Java类中不仅可以定义变量和方法还可以定义类,这样定义在类内部的类就被称为内部类。根据定义方式的不同,内部类分为静态内部类、成员内部类、局部内部类、匿名内部类四种。

一、静态内部类

定义在类内部的静态类,就是静态内部类。静态内部类是定义在外部类的成员位置上,且有static修饰。
Java 集合类HashMap内部就有一个静态内部类NodeNodeHashMap存放元素的类。
HashMap内部维护Node数组存放元素,但是Node对使用者是透明的。像这种和外部类关系密切的,且不依赖外部类实例的,都可以使用静态内部类。
用法:

  • 静态内部类,可以访问外部类的所有静态成员(变量)和方法,即使是private的也一样。但不能直接访问非静态的成员;
  • 可以添加任意访问修饰符,因为它的地位就是一个成员;
  • 作用域和外部类的其他成员一样,是整个类体
  • 静态内部类和一般的类一样,可以定义变量、方法、构造方法等
  • 如果内部类和外部类有成员重名时,遵循就近原则。如果想访问外部类成员,则可以使用“外部类名.成员”;
  • 其他类使用静态内部类需要使用“外部类.静态内部类”方式

代码示例:

public class Monster {

    private String name;

    private static final int TYPE = 1;

    /**
     * 静态内部类
     */
    public static class Sub{
        private static final int TYPE = 2;
        public void printInfo(){
            System.out.println("怪物类型:" + TYPE);
            System.out.println("外部怪物类型:" + Monster.TYPE);
            // 无法访问外部类的 非静态成员
            // System.out.println("怪物name:" + name);
        }
    }

    public static void main(String[] args){
        Monster.Sub sub = new Monster.Sub();
        sub.printInfo();
    }
}

结果:
怪物类型:2
外部怪物类型:1

二、成员内部类

定义在类内部成员位置上的非静态类,就是成员内部类。
用法:

  • 不能定义静态方法和变量(final 修饰的除外)。这是因为成员内部类是非静态的,类初始化的时候先初始化静态成员,如果允许成员内部类定义静态变量,那么成员内部类的静态变量初始化顺序是有歧义的;
  • 可以直接访问外部类的所有成员,包括private。外部类访问成员内部类的访问方式:创建对象,再访问;
  • 作用域与外部类的其他成员一样,是整个类体;
  • 如果内部类和外部类有成员重名时,遵循就近原则。如果想访问外部类成员,则可以使用“外部类名.this.成员”;
  • 外部其他类访问成员内部类的三种方式:1、实例化外部类,通过外部类方法访问;2、将内部类作为外部类的成员实例化然后访问;3、在外部类里编写一个方法返回内部类对象。
    代码示例:
public class Monster {

    private String name;

    private static final int TYPE = 1;

    public Monster(String name){
        this.name = name;
    }

    /**
     * 成员内部类
     * 投掷物
     */
    public class Missile{
        private String name;
        public Missile(String name){
            this.name = name;
        }
        public void printInfo(){
            System.out.println("怪物类型:" + TYPE);
            System.out.println("投掷物名称:" + name);
            System.out.println("怪物名称:" + Monster.this.name);
        }
    }

    public void shutWater(){
        Missile water =  new Missile("水");
        water.printInfo();
    }
	
    public Missile getFire(){
        return new Missile("火焰");
    }

    public static void main(String[] args){
        // 成员内部类
        Monster monster = new Monster("龙");
        // 第一种 通过外部类方法访问
        // monster.shutWater();
        // 第二种 将内部类作为成员实例化访问
        // Monster.Missile thunder = monster.new Missile("雷电");
        // 第三种 外部类方法返回内部类
        Monster.Missile fire = monster.getFire();
        fire.printInfo();
    }
	
结果:
怪物类型:1
投掷物名称:火焰
怪物名称:龙
}

三、局部内部类

定义在方法中的类就是局部内部类。
用法:

  • 可以访问外部类所有成员、方法,包括private。外部类成员可以直接访问;
  • 可以使用final修饰
  • 如果内部类和外部类有成员重名时,遵循就近原则。如果想访问外部类成员,则可以使用“外部类名.this.成员”;
  • 作用域为定义它的方法或代码块中
  • 外部类访问局部内部类方式:创建对象,再访问
  • 外部其他类不能直接访问局部内部类

代码示例:

public class Monster {

    private String name;

    private static final int TYPE = 1;

    public Monster(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    /**
     * 繁衍
     */
    public void multiply(){
        class Egg{
            private String name;
            public Egg(String name){
                this.name = name;
            }
            public void hatch(){
                System.out.println("怪物类型:" + TYPE);
                Monster monster = new Monster("小龙");
                System.out.println("孵化:" +Monster.this.name + " 的 " + name + " 孵化出新的怪物 " + monster.getName());
            }
        }
        Egg egg = new Egg("龙蛋");
        egg.hatch();
    }
    public static void main(String[] args){
        // 局部内部类
        Monster monster = new Monster("龙");
        monster.multiply();
    }
}

结果:
怪物类型:1
孵化:龙 的 龙蛋 孵化出新的怪物 小龙

四、匿名内部类

匿名内部类必须要继承一个类或实现一个接口,直接使用new来生成一个对象的引用。
用法:

  • 匿名内部类是局部内部类的一种简化形式,本质上是一个对象,是实现类该接口或继承了该类的子类对象;
  • 语法格式new 类名或接口名(){ 重写方法 }
  • 经常作为参数或返回值,使用方便
  • 使用匿名内部类可以实现:一个类中嵌套一个接口

代码示例:

public class Monster {

    private String name;

    private static final int TYPE = 1;

    public Monster(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }
    public void multiply(){
        System.out.println("怪物繁衍");
    }
	
    public static void main(String[] args){
        // 匿名内部类
        Monster dragon = new Monster("龙"){
            @Override
            public void multiply(){
                System.out.println(this.getName() + "生小龙");
            }
        };
        dragon.multiply();

        Monster snake = new Monster("蛇"){
            @Override
            public void multiply(){
                System.out.println(this.getName() + "生小蛇");
            }
        };
        snake.multiply();
    }
}
posted @ 2022-12-18 23:19  残忍的幻象饭团  阅读(72)  评论(0)    收藏  举报