关于匿名内部类

java中的匿名内部类概述

1.匿名内部类也就是没有名字的内部类

2.使用场景:在只调用一次的时候,它通常用来简化代码编写,不用定义一个类

3.前提条件:必须继承一个父类或实现一个接口

通常我们的写法:

abstract class Bird {

    public abstract void fly();

}

 

class Eagle extends Bird{

    public void fly() {

        System.out.println("fly in sky");

    }

}

 

public class Demo {

    public static void main(String[] args) {

        Bird b = new Eagle();

        b.fly();

    }

}

执行结果:fly in sky

摘要

Eagle继承了Bird类,然后实现了Eagle的一个实例,将其向上转型为Bird类的引用

但是,我们发现,此时的业务场景Eagle 类只使用了一次,

这个场景就可以使用匿名内部类:

abstract class Bird {

    public abstract void fly();

}

 

public class Demo {

    public static void main(String[] args) {

        Bird b = new Bird() {

            public void fly() {

                System.out.println("fly in sky ");

            }

        };

        b.fly();

    }

}

执行结果:fly in sky 

这里,我们省略了eagle类的书写,直接在Bird类的大括号中实现了fly方法,

匿名内部类还能用于接口上,直接把抽象Bird改成接口就可以了,其他不变。

匿名内部类最直接的使用案例就可以参照多线程的使用上:

Thread:

public class Demo {

    public static void main(String[] args) {

        Thread t = new Thread() {

            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        

        //lambda表达式版
        /*Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.print(i + " ");
            }
        });*/

        t.start();
    }
}

Runnablre

public class Demo {

    public static void main(String[] args) {

        Runnable r = new Runnable() {

            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };

        //lambda表达式版
         /*Runnable r = () -> {
            for (int i = 1; i <= 5; i++) {
                System.out.print(i + " ");
            }
        };*/

        Thread t = new Thread(r);
        t.start();
    }

}

使用的形参为何要为final

public class OuterClass {
    public void display(final String name,String age){
        class InnerClass{
            void display(){
                System.out.println(name);
            }
        }
    }
}

看起来咋样,好像name直接传给内部类了,其实不然, 在java编译之后实际的操作如下:

public class OuterClass$InnerClass {
    public InnerClass(String name,String age){
        this.InnerClass$name = name;
        this.InnerClass$age = age;
    }
    
    
    public void display(){
        System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );
    }
}

事实上内部类并不是直接调用外部方法传递的参数,而是利用自身的构造器对传入的参数进行备份,自己内部方法调用的实际上是自己的属性而不是外部方法传递进来的参数。

      这里想一下就能明白为啥要用final了,在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,就是说在内部类中我对属性的改变并不会影响到外部的形参而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类改变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值