Java内部类

内部类

1. 概述

​ 内部类即在一个类中声明的其他Java类,这些类也称之为嵌套类,内属类;当一个类(B)只为另一个类(A)提供服务,其他类(CDEF…)不可能使用到该类(B)时,此时没有必要单独创建一个java文件来存储这个类(B),因此可以将类(B)在另一个类(A)中直接声明,减少不必要的文件创建。

Java中内部类的种类包含以下四种:

  • 成员内部类
  • 局部内部类
  • 静态内部类
  • 匿名内部类

2. 成员内部类

成员内部类,顾名思义,类似成员变量,成员方法;即直接在外部类结构中定义的一个java类,与成员变量和成员方法同一级别,例如:

public class Outter {

    private String name1;

    public void outerTest(){
        System.out.println("外部类的普通方法");
        Inner i = this.new Inner();
        i.innerTest();
    }

    //成员内部类
    private class Inner{
        private String name2;

        public void innerTest(){
            System.out.println("内部类的测试方法");
            System.out.println(Outter.this);
        }
    }

    public static void main(String[] args) {

        Outter ot = new Outter();
        //创建内部类的实例必须通过外部类的对象创建
        Outter.Inner i = ot.new Inner();
        i.innerTest();
    }
}

注意事项:

  1. 成员内部类与成员变量,成员方法同一级别
  2. 创建成员内部类需要由外部类的对象完成
  3. 可以在内部类中直接访问外部类的成员
  4. 多数时候的成员内部类都是private

3. 局部内部类

局部内部类类似局部变量,一般在一个方法或者语句块中出现,适用范围也只有当前声明区域,若一个类只为一个方法或者一个语句块提供服务,此时没有必要声明全局内部类,更无必要创建一个单独java文件存储,因此,可以将该内部类声明到方法或者语句块中:

public class LocalOuter {

    private String name;

    public void testOutter(){
        int i = 100;
        //创建局部内部类
        class InnerClass{
            private int n = 10;
            public void testInner(){
                System.out.println(n);
                //编译错误,i是方法的局部变量,只能使用不能修改(final)
                //i = 1000;
                System.out.println(i);
            }
        }
        //由于局部内部类在方法内部创建,因此使用范围也只能是方法内部
        InnerClass ic = new InnerClass();
        ic.testInner();
    }

    public static void main(String[] args) {
        LocalOuter lo = new LocalOuter();
        lo.testOutter();
    }

}

注意事项:

  1. 局部内部类不能使用任何的访问修饰符修饰
  2. 局部内部类中可以使用方法或者语句块中声明局部变量,但是只能用,不能修改(该变量会自动标记为final,在java8以前需要手动声明)

4. 静态内部类

静态内部类与静态变量,静态方法的加载顺序,静态内部类理解为使用static修饰的成员内部类;

public class StaticOutter {

    private String name;

    public void testOutter(){
        System.out.println("外部类方法。。。");

        new InnerClass().testInner();
    }

    static class InnerClass{
        private int age;

        public void testInner(){
            System.out.println("静态内部类的方法");
        }
    }

    public static void main(String[] args) {
        //创建静态内部类对象
        StaticOutter.InnerClass si = new StaticOutter.InnerClass();
    }
}

注意事项:

  1. 静态内部类一般用于在一个类中缓存数据,参考java.lang.Integer类中IntegerCache

5. 匿名内部类(重要)

​ 匿名内部类即没有类名名称的内部类,为什么需要匿名内部类:对于一些内部类只需要执行一次(例如:局部内部类),但是根据类的定义方式有需要设置类名称,并根据类名称创建对象,然后执行类中的方法,等于说做了一些不要的事情(类名,创建对象),所以针对以上问题才有了匿名内部类一说。

大多数时候,匿名内部类一般针对抽象类和接口使用。

创建语法:

public class TestInnerClass {

    public void t(){

    }

    public static void main(String[] args) {
        //对接口创建匿名内部类对象
        Flyable f = new Flyable(){
            @Override
            public void fly(){
                System.out.println("fly....");
            }
        };
        f.fly();
        //对普通类创建匿名内部类对象
        User u = new User(){
            @Override
            public void sayHi() {
                System.out.println("hello,laotie!!!");
            }
        };
        u.sayHi();

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2fBLNW0i-1626698218574)(assets/image-20210717133210695.png)]

注意事项

  1. 匿名内部类即没有名字的内部类
  2. 创建匿名内部类时就是在创建匿名内部类的对象
  3. 匿名内部类没有构造器,可以使用初始化块实现构造器的功能

6. 内部类访问当前对象问题

之前有学习过this关键字,this表示调用当前成员的对象;但是如果在内部类中直接使用this,此时的this表示内部类的当前对象,如果需要访问外部类的this,则应该使用外部类的类名称.this,例如:

public class Outter {

    public void outerTest(){
        System.out.println("外部类的普通方法");
    }

    //成员内部类
    private class Inner{

        public void innerTest(){
            System.out.println("内部类的测试方法");
            //访问外部类的当前对象
            System.out.println(Outter.this);
            //访问当前内部类的对象
            System.out.println(this);
        }
    }

}

7. 内部类使用场景

public class Button {

    private String name;

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

    /**按钮被点击时执行*/
    public void onClick(ClickListener c){
        c.click();
    }

    interface ClickListener{
        void click();
    }
}
public class TestButton {

    public static void main(String[] args) {

        Button btn = new Button("发送");
        //使用匿名内部类对象
        btn.onClick(new Button.ClickListener() {
            //回调函数(钩子函数)
            @Override
            public void click() {
                System.out.println("发送成功");
            }
        });

    }
}

8. 内部类的好处

  • 内部类提供了比外方法更好封装性
  • 使用内部类可以解决外部类只能单继承的问题(内部类也能继承其他类)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西伯利亚大熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值