动力节点Java教程2024笔记(515-600集)


以下内容为B站动力节点的JAVA基础课程2024全部内容,课程链接如下:https://www.bilibili.com/video/BV1p7421N7XT/,该笔记根据课程资料整理,顺序按照课程PPT截图整理,附有部分个人的问题和重点整理,如有侵权请联系下架,后续会持续更新整理课程中的重难点,课程中有很多重点和细节部分值得反复思考、消化,个人觉得是很不错的JAVA课程




第十一章 注解

注解概述

在这里插入图片描述

Java预置注解

在这里插入图片描述

自定义注解

在这里插入图片描述

元注解

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

反射注解

在这里插入图片描述

综合练习

在这里插入图片描述

第十二章 网络编程

网络编程概述

在这里插入图片描述

网络编程三要素

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

网络编程基础类

在这里插入图片描述

在这里插入图片描述

TCP与UDP协议

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

基于TCP协议的编程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

基于UDP协议的编程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

第十三章 Lambda表达式

主要内容

  1. Lambda表达式的概述
  2. Lambda表达式的使用
  3. Lambda表达式的方法引用
  4. Lambda表达式的在集合中的使用

学习目标

知识点 要求
Lambda表达式的概述 理解
Lambda表达式的使用 了解
Lambda表达式的方法引用 掌握
Lambda表达式的在集合中的使用 理解

Lambda表达式的概述

Lambda表达式的引入

Lambda表达式是JDK1.8的一个新特性,可以取代大部分的匿名内部类,以便写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。
在以前的学习中,想要实现对List集合的“降序”排序操作,就需要使用匿名内部类来实现,这样的代码非常的复杂和繁琐,代码如下:

// 方式一:使用匿名内部类来实现
List<Integer> list = Arrays.asList(3, 6, 1, 7, 2, 5, 4);
Collections.sort(list, new Comparator<Integer>() {
   
   
    @Override
    public int compare(Integer o1, Integer o2) {
   
   
        return o2 - o1;
    }
});
System.out.println("排序后:" + list);

针对以上对List集合的的“降序”排序操作,除了使用匿名内部类来实现外,还可以使用Lambda表达式来实现,使用Lambda表达式的代码非常优雅,并且还非常的简洁,代码如下:

// 方式二:使用Lambda表达式来实现
List<Integer> list = Arrays.asList(3, 6, 1, 7, 2, 5, 4);
Collections.sort(list, (o1, o2) -> o2 - o1);
System.out.println("排序后:" + list);

函数式编程思想的概述

Java从诞生之日起就一直倡导“一切皆对象”,在Java语言中面向对象(OOP)编程就是一切,但是随着Python和Scala等语言的崛起和新技术的挑战,Java也不得不做出调整以便支持更加广泛的技术要求,即Java语言不但支持OOP还支持OOF(面向函数编程)。
JDK1.8引入Lambda表达式之后,Java语言也开始支持函数式编程,但是Lambda表达式不是Java语言最早使用的,目前C++、C#、Python、Scala等语言都支持Lambda表示。

  • 面向对象的思想
    • 做一件事情,找一个能解决这个事情的对象,然后调用对象的方法,最终完成事情。
  • 函数式编程思想
    • 只要能获得结果,谁去做的,怎么做的都不重要,重视的是结果,不重视实现过程。

在函数式编程语言中,函数被当成一等公民对待。在将函数当成一等公民的编程语言中,Lambda表达式的类型是函数,但是Lambda表达式却是一个对象,而不是函数,它们必须依附于一类特别的对象类型,也就是所谓的函数式接口。
简单点说,JDK1.8中的Lambda表达式就是一个函数式接口的实例,这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以使用Lambda表达式来表示

如何去理解函数式接口

能够使用Lambda表达式的一个重要依据是必须有相应的函数式接口,所谓的函数式接口,指的就是“一个接口中有且只能有一个抽象方法”。也就是说,如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。
如果我们在接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,也就是该接口中有且只能定义一个抽象方法,如果该接口中定义了多个或0个抽象方法,则程序编译时就会报错。
【示例】定义一个函数式接口

@FunctionalInterface
public interface Flyable {
   
   
    // 在函数式接口中,我们有且只能定义一个抽象方法
    void showFly();
    // 但是,可以定义任意多个默认方法或静态方法
    default void show() {
   
   
        System.out.println("JDK1.8之后,接口还可以定义默认方法和静态方法");
    }
}

另外,从某种意义上来说,只要你保证你的接口中有且只有一个抽象方法,则接口中没有使用 @FunctionalInterface 注解来标注,那么该接口也依旧属于函数式接口。
在以下代码中,Flyable接口中没有使用@FunctionalInterface 注解,但是Flyable接口中只存在一个抽象方法,因此Flyable接口依旧属于函数式接口,那么使用Lambda表达式就可以表示Flyable 接口的实例,代码如下:

/**
 * 没有使用@FunctionalInterface标注的接口
 */
public interface Flyable {
   
   
    void showFly();
}
/**
 * 测试类
 */
public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 使用lambda表示来表示Flyable接口的实例
        Flyable flyable = () -> {
   
   
            System.out.println("小鸟自由自在的飞翔");
        };
        // 调用Flyable接口的实例的showFly()方法
        flyable.showFly();
    }
}

Lambda和匿名内部类

  • 所需类型不同
    • 匿名内部类:可以是接口,抽象类,具体类。
    • Lambda表达式:只能是接口。
  • 使用限制不同
    • 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类。
    • 如果接口中有多个抽象方法,则就只能使用匿名内部类,而不能使用Lambda表达式。
  • 实现原理不同
    • 匿名内部类:编译之后,会生成一个单独的.class字节码文件。
    • Lambda表达式:编译之后,没有生成一个单独的.class字节码文件。

Lambda表达式的使用

Lambda表达式的语法

Lambda表达式本质就是一个匿名函数,在函数的语法中包含返回值类型、方法名、形参列表和方法体等,而在Lambda表达式中我们只需要关心形参列表和方法体即可。
在Java语言中,Lambda表达式的语法为“(形参列表) -> {方法体}”,其中“->”为 lambda操作符或箭头操作符,“形参列表”为对应接口实现类中重写方法的形参列表,“方法体”为对应接口实现类中重写方法的方法体。
接下来,我们就以匿名内部类为例,从而将匿名内部类演化为Lambda表达式,代码如下:

List<Integer> list = Arrays.asList(3, 6, 1, 7, 2, 5, 4);
Collections.sort(list, new Comparator<Integer>() {
   
   
    @Override
    public int compare(Integer o1, Integer o2) {
   
   
        return o2 - o1;
    }
});
System.out.println("排序后:" + list);

在以上的匿名内部类中,黄色背景颜色标注的代码都属于不可变的固定代码,而红色背景颜色标注的代码,属于可变的并且是完成该功能的核心代码。因此,将此处的匿名内部类转化为Lambda表达式,我们只需保留红色部分的形参列表和方法体即可,对应的Lambda表达式代码实现如下:

List<Integer> list = Arrays.asList(3, 6, 1, 7, 2, 5, 4);
Collections.sort(list, (Integer o1, Integer o2) -> {
   
   
    return o2 - o1;
});
System.out.println("排序后:" + list);

在以上代码中,黄色背景颜色标注的就是重写于Comparator接口中抽象方法的形参列表,而红色背景颜色标注的就是重写方法对应方法体的代码实现。因此Lambda本质上就是去掉了一堆没有意义的代码,只留下核心的代码逻辑,从而让代码看起来更加的简洁且优雅。

Lambda表达式的使用

Lambda表达式的基本使用

接下来,我们以自定义的函数式接口为例,先从匿名对象的实现过程,慢慢演变为Lambda表达式的实现过程。另外,使用Lambda表达式的时候,则必须有上下文环境,才能推导出Lambda对应的接口类型。

无返回值函数式接口

情况一:无返回值无参数

// 情况一:无返回值无参数
interface NoParameterNoReturn {
   
   
    void test();
}

public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 方式一:使用匿名内部类来实现
        NoParameterNoReturn obj1 = new NoParameterNoReturn() {
   
   
            @Override
            public void test() {
   
   
                System.out.println("无参无返回值");
            }
        };
        obj1.test();

        // 方式二:使用Lambda表达式来实现
        NoParameterNoReturn obj2 = () -> {
   
   
            System.out.println("无参无返回值");
        };
        obj2.test();
    }
}

情况二:无返回值一个参数

// 情况二:无返回值一个参数
interface OneParameterNoReturn {
   
   
    void test(int num);
}

public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 方式一:使用匿名内部类来实现
        OneParameterNoReturn obj1 = new OneParameterNoReturn() {
   
   
            @Override
            public void test(int num) {
   
   
                System.out.println("无返回值一个参数 --> " + num);
            }
        };
        obj1.test(10);

        // 方式二:使用Lambda表达式来实现
        OneParameterNoReturn obj2 = (int num) -> {
   
   
            System.out.println("无返回值一个参数 --> " + num);
        };
        obj2.test(20);
    }
}

情况三:无返回值多个参数

// 情况三:无返回值多个参数
interface MoreParameterNoReturn {
   
   
    void test(String str1, String str2);
}
public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 方式一:使用匿名内部类来实现
        MoreParameterNoReturn obj1 = new MoreParameterNoReturn() {
   
   
            @Override
            public void test(String str1, String str2) {
   
   
                System.out.println(str1 + " : " + str2);
            }
        };
        obj1.test("hello", "world");

        // 方式二:使用Lambda表达式来实现
        MoreParameterNoReturn obj2 = (String str1, String str2) -> {
   
   
            System.out.println(str1 + " : " + str2);
        };
        obj2.test("你好", "世界");
    }
}

有返回值函数接口

情况一:有返回值无参数

// 情况一:有返回值无参数
interface NoParameterHasReturn {
   
   
    int test();
}

public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 方式一:使用匿名内部类来实现
        NoParameterHasReturn obj1 = new NoParameterHasReturn() {
   
   
            @Override
            public int test() {
   
   
                return 520;
            }
        };
        System.out.println(obj1.test()); // 输出:520

        // 方式二:使用Lambda表达式来实现
        NoParameterHasReturn obj2 = () -> {
   
   
            return 1314;
        };
        System.out.println(obj2.test()); // 输出:1314
    }
}

情况二:有返回值一个参数

// 情况二:有返回值一个参数
interface OneParameterHasReturn {
   
   
    String test(double num);
}

public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 方式一:使用匿名内部类来实现
        OneParameterHasReturn obj1 = new OneParameterHasReturn() {
   
   
            @Override
            public String test(double num) {
   
   
                return "传入的小数为:" + num;
            }
        };
        System.out.println(obj1.test(520.0));

        // 方式二:使用Lambda表达式来实现
        OneParameterHasReturn obj2 = (double num) -> {
   
   
            return "传入的小数为:" + num;
        };
        System.out.println(obj2.test(1314.0));
    }
}

情况三:有返回值多个参数

// 情况三:有返回值多个参数
interface MoreParameterHasReturn {
   
   
    String test(int num1, int num2);
}
public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // 方式一:使用匿名内部类来实现
        MoreParameterHasReturn obj1 = new MoreParameterHasReturn() {
   
   
            @Override
            public String test(int num1, int num2) {
   
   
                return "运算的结果为:" + (num1 + num2);
            }
        };
        System.out.println(obj1.test(10, 20));

        // 方式二:使用Lambda表达式来实现
        MoreParameterHasReturn obj2 = (int num1, int num2) -> {
   
   
            return "运算的结果为:" + (num1 + num2);
        };
        System.out.println(obj2.test(20, 30));
    }
}

Lambda表达式的语法精简

在以上代码中,虽然Lambda表达式的语法已经很简洁了,但是Lambda表达式的语法格式还可以更加的精简,从而写出更加优雅的代码,但是相应的代码可读性也会变差。
在以下的应用场景中,我们就可以对Lambda表达式的语法进行精简,场景如下:

  1. 形参类型可以省略,如果需要省略,则每个形参的类型都要省略。
  2. 如果形参列表中只存在一个形参,那么形参类型和小括号都可以省略。
  3. 如果方法体当中只有一行语句,那么方法体的大括号也可以省略。
  4. 如果方法体中只有一条return语句,那么大括号可以省略,且必须去掉return关键字。

接下来,我们就对以下的Lambda表达式代码进行精简,从而写出更加优雅的代码。

public class Test01 {
   
   
    public static void main(String[] args) {
   
   
        // (1)形参类型可以省略,如果需要省略,每个形参的类型都要省略。
        // 没有精简的Lambda表达式代码
        MoreParameterNoReturn obj1 = (String str1, String str2) -> {
   
   
            System.out.println(str1 + " : " + str2);
        };
        obj1.test("hello", "world");
        // 精简之后的Lambda表达式代码
        MoreParameterNoReturn obj2 = (str1, str2) -> {
   
   
            System.out.println(str1 + " : " + str2);
        };
        obj2.test("你好", "世界");

        // (2)如果形参列表中只有一个形参,那么形参类型和小括号都可以省略。
        // 没有精简的Lambda表达式代码
        OneParameterHasReturn obj3 = (double num) -> {
   
   
            return "传入的小数为:" + num;
        };
        System.out.println(obj3.test(520.0));
        // 精简之后的Lambda表达式代码
        OneParameterHasReturn obj4 = num -> {
   
   
            return "传入的小数为:" + num;
        };
        System.out.println(obj4.test(1314.0));

        // (3)如果方法体当中只有一行代码,那么方法体的大括号也可以省略。
        // 没有精简的Lambda表达式代码
        NoParameterNoReturn obj5 = () -> {
   
   
            System.out.println("无参无返回值");
        };
        obj5.test();
        // 精简之后的Lambda表达式代码
        NoParameterNoReturn obj6 = () -> System.out.println("无参无返回值");
        obj6.test();

        // (4)方法体中只有一条return语句,则大括号可以省略,且必须去掉return关键字
        // 没有精简的Lambda表达式代码
        MoreParameterHasReturn obj7 = (int a, int b) -> {
   
   
            return "运算的结果为:" + (a + b);
        };
        System.out.println(obj7.test(10, 20));
        // 精简之后的Lambda表达式代码
        MoreParameterHasReturn obj8 = (a, b) -> "运算的结果为:" + (a + b);
        System.out.println(obj8.test(20, 30));
    }
}

四个基本的函数式接口

名字 接口名 对应的抽象方法
消费 Consumer void accept(T t);
生产 Supplier T get();
转换 Function<T, R> R apply(T t);
判断 Predicate boolean test(T t);

以上的函数式接口都在java.util.function包中,通常函数接口出现的地方都可以使用Lambda表达式,所以不必记忆函数接口的名字,这些函数式接口及子接口在后续学习中很常用。

Lambda表达式的方法引用

方法引用的概述

我们在使用Lambda表达式的时候,如果Lambda表达式的方法体中除了调用现有方法之外什么都不做,满足这样的条件就有机会使用方法引用来实现。
在以下的代码中,在重写的apply()方法中仅仅只调用了现有Math类round()方法,也就意味着Lambda表达式中仅仅只调用了现有Math类round()方法,那么该Lambda表达式就可以升级为方法引用,案例如下:

// 需求:实现小数取整的操作
// 方式一:使用匿名对象来实现
Function<Double, Long> function1 = new Function<Double, Long>() {
   
   
    @Override
    public Long apply(Double aDouble) {
   
   
        return Math.round(aDouble);
    }
};
System.out.println(function1.apply(3.14));

// 方式二:使用Lambda表达式来实现
Function<Double, Long> function2 = aDouble -> Math.round(aDouble);
System.out.println(function2.apply(3.14));

// 方式三:使用方法引用来实现
Function<Double, Long> function3 = Math :: round;
System.out.println(function3.apply(3.14));

对于方法引用,我们可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
在Lambda表达式的方法引用中,主要有实例方法引用、静态方法引用、特殊方法引用和构造方法引用、数组引用这五种情况,接下来我们就对这五种情况进行讲解。

实例方法引用

语法:对象 :: 实例方法
特点:在Lambda表达式的方法体中,通过“对象”来调用指定的某个“实例方法”。
要求:函数式接口中抽象方法的返回值类型和形参列表 与 内部通过对象调用某个实例方法的返回值类型和形参列表 保持一致。
【示例】实例化Consumer接口的实现类对象,并在重写的accept()方法中输出形参的值

// 方式一:使用匿名内部类来实现
Consumer<String> consumer1 = new Consumer<String>() {
   
   
    @Override
    public void accept(String str) {
   
   
        System.out.println(str);
    }
};
consumer1.accept
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值