10行代码搞懂 匿名内部类 & lambda 表达式 & 函数式接口

10行代码搞懂 匿名内部类 & lambda 表达式 & 函数式接口

一、先上总结:

详解看详细代码中的注释。

1、匿名内部类语法:

new 类名或接口名(){
    @Override
    访问修饰符 返回值 方法名(参数...){
        方法体
    }
}

2、lambda 表达式语法:

(参数...) -> {方法体}

3、函数式接口:

  1. 使用 @FunctionalInterface 标记的接口。
  2. @FunctionalInterface 只能标记在只定义了单个抽象方法的接口上。
  3. 接口中的 default 方法和静态方法不算是抽象方法。

二、简化代码:

class Test {
    public static void main(String[] args) {
        Outer.method().show();
        Outer.method2().show();
    }
}

interface Inner {
    void show();
}

class Outer {
    public static Inner method() {
        return new Inner() {
            @Override
            public void show() {
                System.out.println("Hello Anonymous");
            }
        };
    }

    public static Inner method2() {
        return () -> System.out.println("Hello Lambda");
    }
}

三、详细代码:

/**
 * description: 匿名内部类 & lambda 表达式 & 函数式接口
 *
 * @author xiaosaguo
 */
public class AnonymousClassesTest {
    public static void main(String[] args) {
        Outer.method().show();
        Outer.method().show3();
        Inner.show4();

        new Outer().method2().show();
        new Outer().method3().show();
    }
}


@FunctionalInterface
interface Inner {

    /* 函数式接口:
     * 1. 使用 @FunctionalInterface 标记的接口
     * 2. @FunctionalInterface 只能标记在只定义了单个抽象方法的接口上
     * 3. 接口中的 default 方法和静态方法不算是抽象方法
     * 4. 如果接口只有一个抽象方法,没有使用 @FunctionalInterface 标记,也是函数式接口,使用此注解标记只是有更严格的语法约束
     */

    void show();

    // void show2();

    default void show3() {
        System.out.println("show3");
    }

    static void show4() {
        System.out.println("show4");
    }
}


class Outer {
    private int num0 = 0;
    public static int num1 = 10;
    private final int num2 = 20;
    public static final int num3 = 30;

    private int num11 = 11;

    public static Inner method() {
        /* 匿名内部类:
         * 1. 是局部内部类的简化形式
         * 2. 前提:存在一个类或接口(一般是由形参或返回值确定)
         * 3. 匿名内部类的格式:
         *      new 类名或接口名(){
         *          @Override
         *          访问修饰符 返回值 方法名(参数...){
         *              方法体
         *          }
         *      }
         * 4. 本质:相当于 继承该类的一个匿名子类 的对象、实现了该接口的一个匿名实现类的对象
         * 5. 注意:局部内部类访问外部变量,外部变量必须是 final 的,不是匿名内部类。
         * <br>
         *    原因是局部内部类是一个对象,在堆内存中,释放时机(垃圾回收)不确定,
         *    有可能在方法完成后还没被释放。
         *    而局部变量在方法完成后就释放了,之后使用局部内部类(堆内对象),
         *    则无法找到局部内部类中调用的局部变量(方法结束已经释放了),
         *    而使用 final 修饰的变量,在编译后会直接替换成常量。
         * <br>
         * 6. 匿名内部类的优势,没有引用,使用后就可以被垃圾回收了
         * 7. 注意:重写方法时,访问修饰符要大于等于父类的
         * 8. 类名.this 可以限定引用对象
         */
        int num4 = 40;
        return new Inner() {
            int num5 = 50;

            @Override
            public void show() {
                int num6 = 60;
                System.out.println("HelloWorld" + num1 + num3 + num4 + num5 + num6);
            }

            /// @Override
            /// public void show2() {
            ///     System.out.println("HelloWorld2");
            /// }
        };
    }

    public Inner method2() {
        /* lambda 表达式:
         * 1. 简化以匿名内部类形式实现函数式接口的使用(可以将匿名内部类语法简化为 lambda 表达式语法)
         * 2. 语法:
         *          (参数...) -> {方法体}
         *      无参数,无返回值
         *          () -> System.out.println("");
         *      有 1 个参数,无返回值: 
         *      注:参数为1个或方法体为1行时,括号可省略
         *          v -> System.out.println(v);
         *      有多个参数,无返回值
         *          (k,v) -> System.out.println(k+v);
         *      有返回值:
         *          () -> return "";
         *      方法体有多行
         *          (k,v) -> {
         *              System.out.println(k+v);
         *              return k + v;
         *          }
         * 3. 类型推断
         *      方法的参数类型,返回值类型,都是由函数式接口方法定义的,编译器可以自动推断出,即参数部分不用声明参数类型
         * 4. this 的区别:lambda 中没有 this,即 this 为类的 this
         *      区别查看 method2 和 method3
         */
        int num2 = -2;
        return () -> {
            // int num2 = 22;
            System.out.println("HelloWorld" + num0 + num1 + num2 + num3 + this.num2 + Outer.this.num2 + num11);
        };
    }

    public Inner method3() {
        int num7 = 70;
        int num2 = -2;// TODO 这个 num2 暂时不知道如何使用
        return new Inner() {
            int num2 = 22;// this.num2

            @Override
            public void show() {
                int num2 = 99;// num2
                System.out.println("HelloWorld" + num0 + num1 + num2 + num3 + this.num2 + Outer.this.num2 + num11 + num7);
            }
        };
    }
}


  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值