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

news2024/12/29 19:44:51

文章目录

  • 一、内部类概述
  • 二、需要了解的内部类
    • 2.1 静态内部类
    • 2.2 成员内部类
    • 2.3 局部内部类
    • 2.4 面试笔试题
  • 三、匿名内部类
  • 四、Lambda表达式
    • 4.1 Lambda 表达式的概述
    • 4.2 Lambda 表达式的省略规则
    • 4.3 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真题)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/484710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SPSS如何管理数据之案例实训?

文章目录 0.引言1.数据文件的分解2.数据文件的横向合并3.数据文件的纵向合并4.数据文件的变换5.观测量的加权6.根据已存在的变量建立新变量7.产生计数变量8.对变量自身重新赋值9.赋值生成新的变量10.变量取值的求等级11.缺失数据的处理12.数据的汇总13.由变量组到观测量组的重组…

hd debug - DAPLink的资料

文章目录 DAPLink的资料概述笔记库迁出的技巧END DAPLink的资料 概述 查资料时, 看到有DAPLink的资料, 记录一下. 笔记 DAPLink项目分为软件和硬件2部分, 不在一个库中. 总览 : https://daplink.io/ 这个页面上说了软件和硬件项目的库地址. 软件库地址 : https://github.…

余弦相似度算法进行客户流失分类预测

余弦相似性是一种用于计算两个向量之间相似度的方法&#xff0c;常被用于文本分类和信息检索领域。具体来说&#xff0c;假设有两个向量A和B&#xff0c;它们的余弦相似度可以通过以下公式计算&#xff1a; 其中&#xff0c;dot_product(A, B)表示向量A和B的点积&#xff0c;no…

什么是链接库 | 动态库与静态库

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

SPSS如何进行基本统计分析之案例实训?

文章目录 0.引言1.描述性分析2.频数分析3.探索分析4.列联表分析5.比率分析 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对基本统计…

深度学习卷积神经网络学习小结2

简介 经过大约两周左右的学习&#xff0c;对深度学习有了一个初步的了解&#xff0c;最近的任务主要是精读深度学习方向的文献&#xff0c;由于搭建caffe平台失败而且比较耗费时间就没有再尝试&#xff0c;所以并没有做实践方面的工作&#xff0c;本文只介绍了阅读文献学到的知…

JdbcTemplate常用语句代码示例

目录 JdbcTemplate 需求 官方文档 JdbcTemplate-基本介绍 JdbcTemplate 使用实例 需求说明 创建数据库 spring 和表 monster 创建配置文件 src/jdbc.properties 创建配置文件 src/JdbcTemplate_ioc.xml 创建类JdbcTemplateTest测试是否可以正确得到数据源 配置 J…

《程序员面试金典(第6版)面试题 16.10. 生存人数(前缀和思想)

题目描述 给定 N 个人的出生年份和死亡年份&#xff0c;第 i 个人的出生年份为 birth[i]&#xff0c;死亡年份为 death[i]&#xff0c;实现一个方法以计算生存人数最多的年份。 你可以假设所有人都出生于 1900 年至 2000 年&#xff08;含 1900 和 2000 &#xff09;之间。如果…

Spring源码解读——高频面试题

Spring IoC的底层实现 1.先通过createBeanFactory创建出一个Bean工厂&#xff08;DefaultListableBeanFactory&#xff09; 2.开始循环创建对象&#xff0c;因为容器中的bean默认都是单例的&#xff0c;所以优先通过getBean、doGetBean从容器中查找&#xff0c;如果找不到的…

LeetCode-1003. 检查替换后的词是否有效

题目链接 LeetCode-1003. 检查替换后的词是否有效 题目描述 题解 题解一&#xff08;Java&#xff09; 作者&#xff1a;仲景 题挺难懂的&#xff0c;很绕&#xff0c;然后读懂了就很简单了 就是说本来是一个字符串s&#xff0c;abc三个字符可以随便放在s原本字符串的左边或…

删除游戏-类似打家劫舍

198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 1 熟悉打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被…

java+微信小程序,实现chatgpt聊天小程序

chatgp持续火爆,然鹅会用的人其实挺少的,现在使用异步请求的方式,基本可以实现秒回复。并且还基于webSocket编写了一个微信小程序来进行交互,可以直接使用微信小程序来进行体验。 现在我将所有代码都上传了github(链接在文章结尾),大家可以clone下来,部署到服务器上,真…

shell命令

shell命令 打开文本编辑器(可以使用vi/vim创建文本),新建一个test.sh文件&#xff0c;输入一些代码&#xff0c;第一行为固定写法 #!/bin/bash echo hello word#!是一个约定的标记&#xff0c;他告诉系统这个脚本使用什么解释器执行 shell中注释 1.单行注释使用# 2.多行注释…

在Linux服务器上(非root权限)配置anaconda和pytorch的GPU环境

本人小白一枚&#xff0c;加入了导师的课题组之后使用学校的服务器开始炼丹&#xff0c;但是光是配环境就花了好几天&#xff0c;特此记录下。。。。 选择你趁手的工具 链接远程服务器的终端工具有很多&#xff0c;例如xshell等&#xff0c;我选择是的finalshell 下载教程 【…

敏捷ACP.敏捷估计与规划.Mike Cohn.

第一部分 传统规划失败的原因 vs 敏捷规划有效的原因 传统的项目规划方式往往会让我们失望。要回答-一个 新产品的范围/进度/资源的组合问题&#xff0c;传统规划过程不一定会产生令人非常满意的答案和最终产品。以下- -些论据可以支持这个结论: ●大约2/3的项目会显著超…

Linux设备驱动模型(一)

一、sysfs文件系统 sysfs是一个虚拟文件系统&#xff0c;将内核总的设备对象的链接关系&#xff0c;以文件目录的方式表示出来&#xff0c;并提对设备的供读写接口。 二、kobject kobject是内核中对象表示的基类&#xff0c;可以认为所有的内核对象都是一个kobject kobject单…

Docker 持久化存储 Bind mounts

Docker 持久化存储 Bind mounts Bind mounts 的 -v 与 --mount 区别启动容器基于bind mount挂载到容器中的非空目录只读 bind mountcompose 中使用 bind mount 官方文档&#xff1a;https://docs.docker.com/storage/bind-mounts/ Bind mounts 的 -v 与 --mount 区别 如果使用…

Origin如何使用基础功能?

文章目录 0.引言1.菜单栏2.工具栏 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对Origin进行了学习&#xff0c;本文通过《Origin 2022科学绘图与数据》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对软件界面基础功能进行阐述。    1.菜单栏 …

【Linux内核解析-linux-5.14.10-内核源码注释】内核源码中宏定义理解

内核宏定义1 这是Linux内核中的start_kernel函数的一部分代码。它的作用是初始化内核的一些基本组件和数据结构。 asmlinkage: 这是一个函数声明修饰符&#xff0c;指示编译器把函数参数放在堆栈中&#xff0c;而不是寄存器中。 __visible: 这是另一个函数声明修饰符&#x…

第二十六章 碰撞体Collision(上)

在游戏世界中&#xff0c;游戏物体之间的交互都是通过“碰撞接触”来进行交互的。例如&#xff0c;攻击怪物则是主角与怪物的碰撞&#xff0c;触发机关则是主角与机关的碰撞。在DirectX课程中&#xff0c;我们也大致介绍过有关碰撞检测的内容。游戏世界中的3D模型的形状是非常复…