Java内部类总结

成员内部类

  • 内部类可以访问外部类的所有成员。
  • 通过外部类.this.*访问外部类同名成员。
  • 通过外部类.内部类 name=new 外部类().内部类()实例化对象。
  • 内部类中不能有任何static成员。
public class InnerClass1 {
    public int a;
    protected double b;
    char c;
    private String d;

    InnerClass1(int a){
        this.a=a;
    }

    class inner{
        int a;

        inner(int a){
            this.a=a;
        }

        private void A(){
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(InnerClass1.this.a);
        }

        public void B(){
            System.out.println(b);
        }
    }

    public static void main(String[] args) {
        InnerClass1.inner inner=new InnerClass1(10).new inner(5);
        inner.A();
        inner.B();
    }
}

局部内部类

  • 定义在方法里,不能有修饰符,只能在方法里使用。
  • 只能使用外部类的final成员。
  • 除了装逼暂时想不出这东西有什么用了...
/**
 * 局部内部类
 */
public class InnerClass2 {

    final static int a=5;

    public static void main(String[] args) {
        class inner{
            int sum(int n){
                int ans=0;
                for(int i=1;i<=n;i++){
                    ans+=i;
                }
                return ans+a;
            }
        }
        System.out.println(new inner().sum(5));
        System.out.println(new inner().sum(15));
    }
}

静态内部类

  • 静态内部类较为独立,不依赖于外部类,通过外部类.内部类 name=new 外部类.内部类()实例化对象,不需要创建外部类实例。
  • 只能访问外部类的static成员。
/**
 * 静态内部类
 */
public class InnerClass3 {

    int a=5;
    static int b=10;

    static class inner3{
        int a=15;
        static int b=20;

        void A(){
            System.out.println(a);
//            System.out.println(InnerClass3.a);
        }

        static void B(){
            System.out.println(b);
            System.out.println(InnerClass3.b);
        }
    }

    public static void main(String[] args) {
        InnerClass3.inner3 inner3=new InnerClass3.inner3();
        inner3.A();
        InnerClass3.inner3.B();
    }
}

匿名内部类

  • 匿名内部类比较常见,比如回调函数,将匿名内部类作为方法参数传递。
  • 直接使用方法就是接口 name=new 接口(){[重写接口所有函数]}
  • 匿名内部类没有构造器。
  • 匿名内部类可以访问外部方法的局部变量,但必须是final声明的或者实际不变的。
  • 原因是当外部方法结束返回时,内部类对象,方法有可能还在,如果引用的外部的局部变量已经没了,就会发生错误,所以通过final修饰,将局部变量复制一份到内部类中,保证数据的一致性。
public class CallBackUser{
    public static void main(String[] args) {

        int b=5;
//        b=5;

        CallBackSystem callBackServer=new CallBackSystem();
        callBackServer.onBtnClick("CallBack", new CallBack() {
            @Override
            public void fun(String name) {
                System.out.println("Hello "+name+" "+b);
            }
        });
    }
}

回调函数

考虑一个问题,如何让系统调用你写的一个方法? 比如点击某个按钮就执行你写的方法。

  • 我们可以把自己写的函数传给[点击按钮]这个函数,在这个函数里面系统就能调用这个参数(是一个函数),比如Arrays.sort就是一个中间函数,而传进去的匿名内部类(别的语言可以是传递函数指针)就是一个回调函数,sort函数内部就会调用这个compare函数去进行比较,排序。
  • 其他语言比如C++/Python可以直接把函数作为另一个函数的参数传入,从而进行回调操作。

在Java中实现一个简单的回调功能需要以下几步:

  • 规定一个统一的接口
    相当于把要回调的函数封装在这个接口里面,把实现这个接口的匿名内部类传递给调用者(系统)。
public interface CallBack {
    void fun(String name);
}
  • 系统端写好的API函数
    系统写API函数的时候不知道用户具体会传递什么回调函数,只能是根据统一的接口来写代码,所以就调用CallBack类型的参数的对应函数。
public class CallBackSystem {

    public void onBtnClick(String name,CallBack callBack){
        System.out.println("点击按钮后系统调用你写的方法");
        callBack.fun(name);
    }
}
  • 用户调用系统函数,传入回调函数等待系统回调
    这里就用到了匿名内部类,因为系统函数的参数是一个接口类型,所以用户需要一个实现该接口的具体实现类,因为在这里经常需要不同的实现类,所以用匿名内部类是最好的,不需要这个具体的类名。
public class CallBackUser{
    public static void main(String[] args) {
        CallBackSystem callBackServer=new CallBackSystem();
        callBackServer.onBtnClick("CallBack", new CallBack() {
            @Override
            public void fun(String name) {
                System.out.println("Hello "+name);
            }
        });
    }
}

你可能感兴趣的:(Java内部类总结)