Java 基础进阶篇(七):匿名内部类与 Lambda 表达式


一、内部类概述

内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。如 People 类和 Heart 类:

在这里插入图片描述

场景: 当一个事物的内部,还有一个部分需要一个完整的结构进行描述时。

作用: 内部类通常可以方便访问外部类的成员,包括私有的成员;内部类提供了更好的封装性,内部类本身就可以用 private protected 等修饰,封装性可以做更多控制。

注: 外部类不能使用 protected 和 private 修饰。


二、需要了解的内部类

2.1 静态内部类

有static修饰,属于外部类本身。
它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。
在这里插入图片描述

静态内部类创建对象的格式:
在这里插入图片描述

拓展:

1. 静态内部类中是否可以直接访问外部类的静态成员?
  可以,外部类的静态成员只有一份可以被共享访问。

2. 静态内部类中是否可以直接访问外部类的实例成员?
  不可以,外部类的实例成员必须用外部类对象访问。

总结: 静态内部类可以直接访问外部类的静态成员,不能直接访问外部类的实例成员。


2.2 成员内部类

无 static 修饰,属于外部类的对象。
JDK 16之前,成员内部类中不能定义静态成员,JDK 16开始也可以定义静态成员了。
在这里插入图片描述
成员内部类创建对象的格式:
在这里插入图片描述

拓展:

1. 成员内部类中是否可以直接访问外部类的静态成员?
  可以,外部类的静态成员只有一份可以被共享访问。

2. 成员内部类的实例方法中是否可以直接访问外部类的实例成员?
  可以,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。

总结: 可以直接访问外部类的静态成员,实例方法中可以直接访问外部类的实例成员。


2.3 局部内部类

局部内部类放在方法、代码块、构造器等执行体中。
局部内部类的类文件名为: 外部类$N内部类.class,N 代表索引,从 1 开始。


2.4 面试笔试题

请观察如下代码,写出合适的代码对应其注释要求输出的结果。

在这里插入图片描述

class People{
    private int heartbeat = 150;
    /**
       成员内部类
     */
    public class Heart{
        private int heartbeat = 110;
        public void show(){
            int heartbeat = 78;
            System.out.println(heartbeat); // 78
            System.out.println(this.heartbeat); // 110
            System.out.println(People.this.heartbeat); // 150
            System.out.println(new People().heartbeat); // 150
        }
    }
}

注意: 在成员内部类中访问所在外部类对象 ,格式:外部类名.this


三、匿名内部类

本质上是一个没有名字的局部内部类,定义在方法中、代码块中等。

作用: 方便创建子类对象,最终目的为了简化代码编写。

格式:

在这里插入图片描述

如:new Employee{… }{…} 就是匿名内部类。

在这里插入图片描述

特点总结:

① 匿名内部类是一个没有名字的内部类。
② 匿名内部类写出来就会产生一个匿名内部类的对象。
③ 匿名内部类的对象类型相当于是当前 new 的那个的类型的子类类型。

举例:

interface Swimming{
    void swim();
}
public class Test {
    public static void main(String[] args) {
        Swimming ss = new Swimming() {
            @Override
            public void swim() {
                System.out.println("老师游泳!");
            }
        };
        go(ss); // 老师游泳!
        
        // 匿名内部类可以作为方法的实际参数进行传输
        go(new Swimming() {
            @Override
            public void swim() {
                System.out.println("学生游泳!");
            }
        });  // 学生游泳!
    }

    public static void go(Swimming s){
        s.swim();
    }
}

对比写一个学生类和老师类实现 Swimming 接口,匿名内部类使得代码更加的简化


四、Lambda表达式

4.1 Lambda 表达式的概述

Lambda 表达式是 JDK 8 开始后的一种新语法形式,其用于简化匿名内部类的代码写法

格式:
在这里插入图片描述
注意:Lambda 表达式只能简化函数式接口的匿名内部类的写法形式

函数式接口:首先必须是接口(抽象类不可以)其次接口中有且仅有一个抽象方法的形式

通常函数式接口用 @FunctionalInterface 注解进行标注,起到只能定义一个抽象方法的限制作用。


4.2 Lambda 表达式的省略规则

  1. 参数类型可以省略不写。

  2. 如果只有一个参数,参数类型可以省略,同时 () 也可以省略。

  3. 如果 Lambda 表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号 “;”

  4. 如果 Lambda 表达式的方法体代码只有一行代码。可以省略大括号不写。
    此时,如果这行代码是 return 语句,必须省略 return,同时也必须省略 “;”。


4.3 Lambda 的使用

举例:自定义数组的排序规则,让其降序排序。
在这里插入图片描述
sort(T[] a, Comparator<? super T > c);

参数一: 被排序的数组 必须是引用类型的元素。 参数二: 代表了一个比较器对象。

该比较器对象是一个函数式接口,因此有两种方案:一种是匿名内部类的形式,另一种是比较类实现该接口的方法。

注: ? super T:代表泛型下限,? 必须是 T 或者其父类。

在这里插入图片描述

方式一:匿名内部类

public class Test2 {
    public static void main(String[] args) {
        // 定义数组
        Integer[] ages = {34, 12, 42, 23};

        // 匿名内部类
        Arrays.sort(ages, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1; //  降序
            }
        });
        // 简化形式 1
        Arrays.sort(ages, (Integer o1, Integer o2) ->{
            return o2 - o1;
        });
        // 简化形式 2
        Arrays.sort(ages, (o1, o2) ->{
            return o2 - o1;
        });

        // 简化形式 3
        Arrays.sort(ages, (o1, o2) -> o2 - o1 );
    }
}

方式二:子类实现

public class Test2 {
    public static void main(String[] args) {
        Integer[] ages = {34, 12, 42, 23};
        Arrays.sort(ages, new Comp());
        System.out.println(Arrays.toString(ages)); // [42, 34, 23, 12]
    }
}
class Comp implements Comparator<Integer>{
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2-o1;
    }
}

文章参考:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程(含Java项目和Java真题)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Xiu Yan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值