反射、枚举及lambda表达式

news2024/10/7 6:39:20

文章目录

  • 一、反射
    • 1.1 定义和用途
    • 1.2 反射基本信息
    • 1.3 反射相关的类(重要)
    • 1.4 Class类(反射机制的起源)
    • 1.5 反射优缺点
    • 1.6 总结
  • 二、枚举
    • 2.1 定义
    • 2.2 使用
    • 2.3 枚举优缺点
    • 2.4 枚举和反射
    • 2.5 总结
  • 三、lambda表达式
    • 3.1 背景
    • 3.2 基本使用
    • 3.3 变量捕获
    • 3.4 在集合当中的使用
    • 3.5 总结

一、反射

1.1 定义和用途

定义:Java的反射机制是在运行状态中对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制
用途

  • 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法
  • 反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。

1.2 反射基本信息

Java程序中许多对象在运行时会出现两种类型:运行时类型和编译时类型,例如Person p = new Student();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实信息。而通过使用反射程序就能判断出该对象和类属于哪些类。

1.3 反射相关的类(重要)

在这里插入图片描述

1.4 Class类(反射机制的起源)

Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件,被编译后的Java文件 (.class)也被JVM解析为一个对象,这个对象就是 java.lang.Class。这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例就可以获得甚至去添加改变这个类的属性和动作,使这个类成为一个动态的类。
1. Class类中的相关方法

  • 常用获得类相关方法**(重要)**
    在这里插入图片描述

  • 常用获得类中属性相关的方法**(重要)**(以下方法返回值为Field相关)
    在这里插入图片描述

  • 获得类中构造器相关的方法**(重要)**(以下方法返回值为Constructor相关)
    在这里插入图片描述

  • 获得类中方法相关的方法**(重要)**(以下方法返回值为Method相关)
    在这里插入图片描述

  • 获得类中注解相关的方法(了解)
    在这里插入图片描述

2. 反射示例
2.1 获得Class对象的三种方式
在反射前,需要做的第一步是拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的,即:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息
第一种:使用Class.forName(“类的全路径名”),静态方法。
前提:已明确类的全路径名
第二种:使用**.class方法。
说明:仅适合在编译前就已经明确要操作的 Class
第三种:使用
类对象的getClass()**方法。
在这里插入图片描述
Student类放在包reflect中。

class Student{
   //私有属性name
   private String name = "hello";
   //公有属性age
   public int age = 18;
   //不带参数的构造方法
   public Student(){
     System.out.println("Student():公开的且不带参数的构造方法");
   }
   private Student(String name,int age) {
      this.name = name;
	  this.age = age;
	  System.out.println("Student(String,name):私有的且带两个参数的构造方法");
   }
   private void eat(){
	  System.out.println("私有的方法,正在吃饭");
   }
   public void sleep(){
      System.out.println("公有的方法,正在睡觉");
   }
   private void function(String str) {
      System.out.println("私有的方法,str"+str);
   }
   @Override
   public String toString() {
      return "Student{" +
	  "name='" + name + '\'' +
	  ", age=" + age +
	  '}';
	  }
   }
public class Text {
    public static void main(String[] args) {
        // 1.通过getClass获取Class对象
        Student student1 = new Student();
        Class class1 = student1.getClass();
        /*
            2.直接通过 类名.class 的方式得到,该方法最安全可靠,程序性能更高
            说明任何一个类都有一个隐含的静态成员变量 class
         */
        Class class2 = Student.class;
        /*
            3.通过 Class对象的 forName() 静态方法来获取,用的最多
            注意这里是类的全路径,如果有包需要加包的路径
            可能抛出 ClassNotFoundException 异常
         */
        Class class3 = null;
        try{
            class3 = Class.forName("reflect.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(class1);//class reflect.Student
        System.out.println(class2);//class reflect.Student
        System.out.println(class3);//class reflect.Student
        /*
           一个类在 JVM 中只会有一个 Class 实例
         */
        System.out.println(class1 == class2);//true
        System.out.println(class1 == class3);//true
        System.out.println(class2 == class3);//true
    }
}

2.2 反射的使用
接下来开始使用反射,反射上面的Student类,把反射的逻辑写到另外的类当中进行理解
注意:所有和反射相关的包都在 import java.lang.reflect 包下面

package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectText {
    //创建对象
    public static void reflectNewInstance(){
        try{
            Class<?> classStudent = Class.forName("reflect.Student");
            //                                       创建类的实例
            Student student = (Student) classStudent.newInstance();
            /*
              Student():公开的且不带参数的构造方法
              Student{name='hello', age=18}
              以上为打印结果
            */
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    //反射私有的构造方法,屏蔽共有构造方法
    public static void reflectPrivateConstructor(){
        try {
            Class<?> classStudent = Class.forName("reflect.Student");
            //注意传入对应的参数
            Constructor<?> declaredconstructorStudent = classStudent.getDeclaredConstructor(String.class,int.class);
            ///设置为true后可修改访问权限  此时,私有的构造方法为公有
            declaredconstructorStudent.setAccessible(true);
            Student student = (Student) declaredconstructorStudent.newInstance("wangwu",15);
            /*
            Student(String,name):私有的且带两个参数的构造方法
            获取私有构造函数并修改姓名和年龄:Student{name='wangwu', age=15}
            以上为打印内容
             */
            System.out.println("获取私有构造函数并修改姓名和年龄:"+student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //反射私有属性
    public static void reflectPrivateField(){
        try {
            Class<?> classStudent = Class.forName("reflect.Student");
            Field field = classStudent.getDeclaredField("name");
            field.setAccessible(true);
            //可以修改该属性的值
            Student student = (Student) classStudent.newInstance();
            field.set(student,"小明");
            /*
            Student():公开的且不带参数的构造方法
            Student{name='小明', age=18}
            以上为打印内容
             */
            System.out.println(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //反射私有方法
    public static void reflectPrivateMethod() {
        try {
            Class<?> classStudent = Class.forName("reflect.Student");
            //                                                            方法名     参数
            Method methodStudent = classStudent.getDeclaredMethod("function", String.class);
            //私有的要加setAccessible(true) 才能使用
            methodStudent.setAccessible(true);
            Student student = (Student) classStudent.newInstance();
            /*
            Student():公开的且不带参数的构造方法
            私有的方法,str反射私有的方法并调用
            以上为打印内容
             */
            methodStudent.invoke(student,"反射私有的方法并调用");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        reflectPrivateMethod();
    }
}

1.5 反射优缺点

优点

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
  3. 反射已经运用在很多流行框架如:Struts、Hibernate、Spring 等等
    缺点
  4. 使用反射会有效率问题。会导致程序效率降低。
  5. 反射技术绕过源代码的技术,会带来维护问题。反射代码比相应的直接代码更复杂 。

1.6 总结

  1. 反射意义:当某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放时,可以通过反射来获取所需的私有成员或是方法
  2. 反射重要的几个类: Class类 、Field类、 Method类、 Constructor类
  3. 学会合理利用反射,一定要在安全环境下使用。

二、枚举

2.1 定义

枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:

public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;

但常量定义有不好的地方,例如:可能碰巧有个数字1,但有可能误会为是RED,现在可以直接用枚举进行组织,这样一来,就拥有了类型(枚举类型),而不是整型1。

public enum TestEnum {
   RED,BLACK,GREEN;
}

优点:将常量组织起来统一进行管理
场景:错误状态码,消息类型,颜色的划分,状态机等。
本质:是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但其默认继承这个类

2.2 使用

1.switch语句

public enum EnumText {
    RED,BLACK,GREEN,WHITE;

    public static void main(String[] args) {
        EnumText enumText1 = EnumText.RED;
        EnumText enumText2 = EnumText.BLACK;
        EnumText enumText3 = EnumText.GREEN;
        System.out.println(enumText1);//RED
        System.out.println(enumText2);//BLACK
        System.out.println(enumText3);//GREEN
        switch (enumText1){
            case RED:
                System.out.println("red");
                break;
            case BLACK:
                System.out.println("black");
                break;
            case GREEN:
                System.out.println("green");
                break;
            case WHITE:
                System.out.println("white");
                break;
            default:
                break;
        }
    }
}

2.Enum类常用方法
在这里插入图片描述

public enum EnumText {
    RED,BLACK,GREEN,WHITE;

    public static void main(String[] args) {
        //.values()获取枚举类型所有成员
        EnumText[] enumText1 = EnumText.values();
        for (int i = 0; i < enumText1.length; i++) {
            //.ordinal()获取枚举成员索引位置
            //RED: 0
            //BLACK: 1
            //GREEN: 2
            //WHITE: 3
            System.out.println(enumText1[i]+": "+enumText1[i].ordinal());
        }
        System.out.println(EnumText.valueOf("GREEN"));//GREEN
    }
}
public enum EnumText {
    RED,BLACK,GREEN,WHITE;

    public static void main(String[] args) {
        EnumText enumText1 = EnumText.RED;
        EnumText enumText2 = EnumText.BLACK;
        System.out.println(enumText1.compareTo(enumText2));//-1
        System.out.println(RED.compareTo(enumText2));//-1
        System.out.println(RED.compareTo(BLACK));//-1
    }
}

在Java当中枚举实际上就是一个类,在定义枚举时,还可以这样定义和使用枚举:
重要:枚举的构造方法默认是私有的

public enum EnumText2 {
    RED("red",1),BLACK("black",2),GREEN("green",3),WHITE("white",4);//枚举成员必须在第一行
    private String name;
    private int key;

    /**
     * 当枚举对象有参数后,需要提供相应的构造方法,且构造方法是私有的
     * @param name
     * @param key
     */
    private EnumText2(String name,int key){
        this.name = name;
        this.key = key;
    }
    public static EnumText2 getEnumKey(int key){
        for (EnumText2 enumText2:EnumText2.values()) {
            if (enumText2.key == key){
                return enumText2;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(getEnumKey(0));//null
        System.out.println(getEnumKey(1));//RED
    }
}

2.3 枚举优缺点

优点

  1. 枚举常量更简单安全
  2. 枚举具有内置方法 ,代码更优雅
    缺点
  3. 不可继承,无法扩展

2.4 枚举和反射

1.枚举是否可以通过反射,拿到实例对象呢?
通过对上述反射的了解,可以知道,任何一个类,哪怕其构造方法是私有的,我们也可以通过反射拿到他的实例对象,那么枚举的构造方法也是私有的,我们是否可以拿到呢?接下来,我们来实验一下:

public enum EnumText2 {
    RED("red",1),BLACK("black",2),GREEN("green",3),WHITE("white",4);
    private String name;
    private int key;

    /**
     * 当枚举对象有参数后,需要提供相应的构造方法,且构造方法是私有的
     * @param name
     * @param key
     */
    private EnumText2(String name,int key){
        this.name = name;
        this.key = key;
    }
    //获取key对应的枚举成员
    public static EnumText2 getEnumKey(int key){
        for (EnumText2 enumText2:EnumText2.values()) {
            if (enumText2.key == key){
                return enumText2;
            }
        }
        return null;
    }
    //获取枚举的私有构造方法
    public static void reflectPrivateConstructor() {
        try {
            //                   获取Class对象:EnumText2
            Class<?> classEnum = Class.forName("enums.EnumText2");
            //获取私有构造方法                                  当前枚举类是提供了两个参数分别是String和int
            Constructor<?> declaredConstructorEnum = classEnum.getDeclaredConstructor(String.class,int.class);
            // 设为true 修改构造方法访问权限
            declaredConstructorEnum.setAccessible(true);
            //                                                        创建类的实例
            EnumText2 enumText2 = (EnumText2) declaredConstructorEnum.newInstance("蓝色",555);
            System.out.println("获取枚举的私有构造方法:"+enumText2);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        reflectPrivateConstructor();
    }
}

运行结果:
在这里插入图片描述
异常信息是: java.lang.NoSuchMethodException: TestEnum.(java.lang.String, int) ,意思是:就是没有对应的构造方法,所有的枚举类,都是默认继承与 java.lang.Enum ,继承了父类除构造函数外的所有东西,并且子类要帮助父类进行构造!而我们写的类,并没有帮助父类构造,那意思是,我们要在自己的枚举类里面,提供super吗?不是的,枚举比较特殊,虽然写的是两个,但是默认他还添加了两个参数,哪两个参数呢?我们看一下Enum类的源码:

protected Enum(String name, int ordinal) {
   this.name = name;
   this.ordinal = ordinal;
}

也就是说,自己的构造函数有两个参数一个是String一个是int,同时他默认后边还会给两个参数,一个是String一个是int,也就是说,这里我们正确给的是4个参数

//获取枚举的私有构造方法
    public static void reflectPrivateConstructor() {
        try {
            //                   获取Class对象:EnumText2
            Class<?> classEnum = Class.forName("enums.EnumText2");
            //获取私有构造方法                         提供了4个参数分别是String、int、String、int
            Constructor<?> declaredConstructorStudent=
                    classEnum.getDeclaredConstructor(String.class,int.class,String.class,int.class);
            // 设为true 修改构造方法访问权限
            declaredConstructorStudent.setAccessible(true);
            //                                                        创建类的实例
            EnumText2 enumText2 = (EnumText2)declaredConstructorStudent.newInstance("父类参数",222,"蓝色",555);

            System.out.println("获取枚举的私有构造方法:"+enumText2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

运行结果:
在这里插入图片描述
此时的异常信息是:IllegalArgumentException,提示我们不能反射地创建枚举对象,即不能通过反射获取枚举类的实例

2.5 总结

  1. 枚举本身就是一个类,其构造方法默认为私有的,且都是默认继承与 java.lang.Enum
  2. 枚举可以避免反射和序列化问题
  3. 枚举的优点和缺点

三、lambda表达式

3.1 背景

Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(可以是一个表达式或一个代码
块)。 Lambda 表达式,基于数学中的λ演算得名,也可称为闭包。
1.Lambda 表达式语法

基本语法: (parameters) -> expression(parameters) ->{ statements; }

  1. paramaters类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个参数时可以省略掉括号。
  2. ->:可理解为“被用于”的意思
  3. 方法体:可以是表达式或代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反
    ,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。
// 1. 不需要参数,返回值为 2
() -> 2
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的和
(x, y) -> x + y
// 4. 接收2个int型整数,返回他们的乘积
(int x, int y) -> x * y
// 5. 接收一个 String 对象,并打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

2.函数式接口

要了解Lambda表达式,首先需要了解什么是函数式接口,函数式接口定义:一个接口有且只有一个抽象方法
注意:

  1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
  2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接
    口,这样如果有两个抽象方法,程序编译就会报错的。
    定义方式:
@FunctionalInterface
interface NoParameterNoReturn {
   //注意:只能有一个方法
   void test();
}

但这种方式也是可以的:

@FunctionalInterface
interface NoParameterNoReturn {
   void test();
   default void test2() {
      System.out.println("函数式接口中的普通方法");
   }
}

3.2 基本使用

先准备好几个接口:

//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
   void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
   void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
   void test(int a,int b);
}
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
   int test();
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
   int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
   int test(int a,int b);
}

Lambda可以理解为:Lambda就是匿名内部类的简化,实际上是创建了一个类,实现了接口,重写了接口的方法。

没有使用lambda表达式的时候的调用方式 :

//                                       匿名内部类 实现NoParameterNoReturn接口
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
     @Override
     public void test() {
          System.out.println("实现接口中无参数无返回值的方法");
     }
};
noParameterNoReturn.test();

具体使用见以下示例代码:

public class LambdaText {
    public static void main(String[] args) {
        //无参数无返回值
        NoParameterNoReturn noParameterNoReturn = ()-> System.out.println("重写接口中无参数无返回值的方法text()");
        noParameterNoReturn.test();
        //有一个参数无返回值
        OneParameterNoReturn oneParameterNoReturn = a-> System.out.println("重写接口中 有一个参数无返回值的方法 text()"+a);
        oneParameterNoReturn.test(10);
        //有多个参数无返回值
        MoreParameterNoReturn moreParameterNoReturn = (a,b)-> System.out.println("重写接口中 有多个参数无返回值的方法 text()"+(a+b));
        moreParameterNoReturn.test(10,15);

        //无参数有返回值
        NoParameterReturn noParameterReturn = ()-> {System.out.println("重写接口中 无参数有返回值的方法text()");return 1;};
        noParameterReturn.test();
        //有一个参数有返回值
        OneParameterReturn oneParameterReturn = a -> {System.out.println("重写接口中 有一个参数有返回值的方法text()"+a);return 2;};
        oneParameterReturn.test(10);
        //有多个参数有返回值
        MoreParameterReturn moreParameterReturn = (a,b)-> {System.out.println("重写接口中 有多个参数有返回值的方法text()"+(a+b));return 3;};
        moreParameterReturn.test(10,15);
    }
}

总结:

  1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略
  2. 参数的小括号里面只有一个参数,那么小括号可以省略
  3. 如果方法体当中只有一句代码(非return语句),那么大括号可以省略
  4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字。方法体中只要有return语句,都需要大括号。

3.3 变量捕获

Lambda 表达式中存在变量捕获 ,了解了变量捕获之后,我们才能更好的理解Lambda 表达式的作用域 。Java当
中的匿名类中,会存在变量捕获。
1.匿名内部类
匿名内部类就是没有名字的内部类 ,这里只是为了说明变量捕获,故匿名内部类只要会使用就好,那么下面我们来简单的看看匿名内部类的使用就好了。
匿名内部类详解

class Text{
    public void  func(){
        System.out.println("func()");
    }
}
public class AnonymityText {
    public static void main(String[] args) {
        new Text(){
            @Override
            public void func() {
                System.out.println("创建内部类,重写Text中的普通方法func()");
            }
        };
    }
}

在上述代码当中的main函数当中,就是一个匿名内部类的简单的使用。
2.匿名内部类的变量捕获

class Text{
    public void  func(){
        System.out.println("func()");
    }
}
public class AnonymityText {
    public static void main(String[] args) {
        int a = 100;
        new Text(){
            @Override
            public void func() {
                System.out.println("创建内部类,重写Text中的普通方法func()");
                System.out.println("内部类捕获到一个变量a:"+a);
            }
        };
    }
}

在上述代码中的变量a就是捕获的变量,这个变量要么是被final修饰,要么是没有改变过值的变量。如下代码就是错误的代码:

public class AnonymityText {
    public static void main(String[] args) {
        int a = 100;
        new Text(){
            @Override
            public void func() {
                a = 90;
                System.out.println("创建内部类,重写Text中的普通方法func()");
                System.out.println("内部类捕获到一个变量a:"+a);
            }
        };
    }
}
public class AnonymityText {
    public static void main(String[] args) {
        int a = 100;
        new Text(){
            @Override
            public void func() {
                System.out.println("创建内部类,重写Text中的普通方法func()");
                System.out.println("内部类捕获到一个变量a:"+a);
                 a = 90;
            }
        };
    }
}

上述代码编译报错
3.Lambda的变量捕获
在Lambda当中也可以进行变量的捕获

//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}
public static void main(String[] args) {
        int a = 100;
        NoParameterNoReturn noParameterNoReturn = ()-> {
            // int a = 90; error
            System.out.println("捕获变量a:"+a);
        };
        noParameterNoReturn.test();
    }

3.4 在集合当中的使用

为了能够让Lambda和Java的集合类集更好的一起使用,集合当中也新增部分接口,以便与Lambda表达式对
接。
在这里插入图片描述
注意:Collection的forEach()方法是从接口 java.lang.Iterable 拿过来的。
1.Collection接口

forEach() 方法演示,该方法在接口 Iterable 当中,原型如下:

default void forEach(Consumer<? super T> action) {
   Objects.requireNonNull(action);
   for (T t : this) {
      action.accept(t);
   }
}

该方法表示:对容器中的每个元素执行action指定的动作 。

public static void main(String[] args) {
   ArrayList<String> list = new ArrayList<>();
   list.add("Hello");
   list.add("lambda");
   list.forEach(new Consumer<String>(){
      @Override
      public void accept(String str){
          //简单遍历集合中的元素
         System.out.print(str+" ");
      }
   });
}

输出结果:Hello lambda
可以修改为如下代码:

public static void main(String[] args) {
   ArrayList<String> list = new ArrayList<>();
   list.add("Hello");
   list.add("lambda");
   //表示调用一个不带参数的方法,其执行花括号内的语句,为原来的函数体内容。
   list.forEach(s -> {
      System.out.println(s);
   });
}

2.List接口

sort()方法的演示
sort方法源码:该方法根据c指定的比较规则对容器元素进行排序。

public void sort(Comparator<? super E> c) {
   final int expectedModCount = modCount;
   Arrays.sort((E[]) elementData, 0, size, c);
   if (modCount != expectedModCount) {
       throw new ConcurrentModificationException();
   }
   modCount++;
}

示例:

public static void main(String[] args) {
   ArrayList<String> list = new ArrayList<>();
   list.add("Hello");
   list.add("lambda");
   list.sort(new Comparator<String>() {
      @Override
      public int compare(String str1, String str2){
         //注意这里比较长度
         return str1.length()-str2.length();
      }
   });
   System.out.println(list);
}

输出结果: Hello, lambda
修改为lambda表达式:

public static void main(String[] args) {
   ArrayList<String> list = new ArrayList<>();
   list.add("Hello");
   list.add("lambda");
   //调用带有2个参数的方法,且返回长度的差值
   list.sort((str1,str2)-> str1.length()-str2.length());
   System.out.println(list);
}

输出结果:Hello,lambda

3.5 总结

Lambda表达式的优点很明显,在代码层次上来说,使代码变得非常的简洁。缺点也很明显,代码不易读。
优点

  1. 代码简洁,开发迅速
  2. 方便函数式编程
  3. 非常容易进行并行计算
  4. Java 引入 Lambda,改善集合操作
    缺点
  5. 代码可读性变差
  6. 在非并行计算中,很多计算未必有传统的 for 性能高
  7. 不容易进行调试

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

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

相关文章

家庭WIFI路由器、无线网卡购买指南

一、参考资料 【Wi-Fi】802.11/802.11b/802.11g/802.11n/802.11a/802.11ac/802.11ax/802.11be 从带宽到路由&#xff0c;从有线到无线&#xff0c;从需求到选购&#xff0c;从布网到实测&#xff0c;全部说尽。基础篇&#xff08;1&#xff09; 【一文详解】802.11a/b/g/n/ac/…

【28】c++设计模式——>观察者模式(1)

观察者模式概念 C观察者模式&#xff08;Observer Pattern&#xff09;是一种设计模式&#xff0c;它用于在对象之间建立一种一对多的依赖关系。在该模式中&#xff0c;当一个对象&#xff08;称为主题&#xff09;发生变化时&#xff0c;所有依赖于它的对象&#xff08;称为观…

跳跃游戏Ⅱ-----题解报告

题目&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 与Ⅰ不同的是&#xff0c;这次要求找出最小的跳跃次数。思路也很简单&#xff0c;在每一次跳跃之后都更新最远的跳跃距离。 举个列子&#xff1a; 输入&#xff1a;2,3,1,1,4 第一次…

【SSA-BP预测】基于麻雀算法优化BP神经网络回归预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Linux 中监控磁盘分区使用情况的 10 个工具

在本文[1]中&#xff0c;我们将回顾一些可用于检查 Linux 中磁盘分区的 Linux 命令行实用程序。 监控存储设备的空间使用情况是系统管理员最重要的任务之一&#xff0c;它可以确保存储设备上有足够的可用空间&#xff0c;以维持 Linux 系统的高效运行。 1. fdisk fdisk 是一个强…

STM32+摁键与定时器实现Led灯控制(中断)

中断作为单片机开发必须掌握的内容&#xff0c;它能够在不搭载操作系统的情况下让我们体验多任务处理的快感&#xff0c;保证了高优先级任务的实时性&#xff0c;同时系统中断也能够提供给用户在核心发生错误之后进行处理的机会。STM32F103系列单片机中断非常强大&#xff0c;每…

SpringBoot +JdbcTemplate+VUE 实现在线输入SQL语句返回数据库结果

文章目录 前言框架选型SpringBoot 结合JdbcTemplate简单示例SpringBoot 结合JdbcTemplate实现运行SQL处理思路后端处理前端处理 前言 想起来要做这个功能是因为我们公司的预生产环境和生产环境如果想要连接数据库都需要登录堡垒机&#xff0c;然后再通过堡垒机进行跳转到对应定…

1024 蓝屏漏洞攻防战(第十九课)

1024 蓝屏漏洞攻防战(第十九课) 思维导图 一 永恒之蓝的介绍 漏洞为外界所知源于勒索病毒的爆发,该病毒利用NSA(美国国家安全局)泄露的网络攻击工具 永恒之蓝( EternalBlue )改造而成,漏洞通过TCP的445和139端口,利用SMB远程代码执行漏洞,攻击者可以在目标系统上执行…

详解对于ReadView 机制如何判断当前事务能够看见

ReadView 机制就是用来判断当前事务能够看见哪些版本的&#xff0c;一个 ReadView 主要包含如下几个部分&#xff1a; m_ids&#xff1a;生成 ReadView 时有哪些事务在执行但是还没提交的&#xff08;称为 “活跃事务”&#xff09;&#xff0c;这些活跃事务的 id 就存在这个字…

for、while、do While、for in、forEach、map、reduce、every、some、filter的使用

for、while、do While、for in、forEach、map、reduce、every、some、filter的使用 for let arr [2, 4, 6, 56, 7, 88];//for for (let i 0; i < arr.length; i) {console.log(i : arr[i]) //0:2 1:4 2:6 3:56 4:7 5:88 }普通的for循环可以用数组的索引来访问或者修改…

AI篇-如何用AI辅助对图片进行鉴赏

前言 目录 前言 一、观众侧鉴赏图片 方法1&#xff1a;直接将图片发给文心一言&#xff0c;让文心一言分析。 方法2&#xff08;正确方法&#xff09;&#xff1a;将图片简单介绍并把图片发给文心一言&#xff0c;让文心一言分析。 二、作者介绍图片 方法&#xff08;正…

智慧公厕管理系统:让公厕更智能、更高效的利器

公厕是城市基础设施的重要组成部分&#xff0c;然而&#xff0c;由于管理不善和公共卫生意识的薄弱&#xff0c;公厕经常面临着脏乱差的问题&#xff0c;令人不愿意使用。为了改善公厕管理的现状&#xff0c;智慧公厕管理系统的出现成为了一种创新的解决方案。 智慧公厕管理系…

大模型微调发展-学习调研总结

模型微调前言 https://blog.csdn.net/weixin_39663060/article/details/130724730 针对于小公司&#xff0c;如何能够利用开源的大模型&#xff0c;在自己的数据上继续训练&#xff0c;从而应用于自己的业务场景&#xff1f;或低成本的方法微调大模型。 目前主流的方法包括201…

小程序之微信登录授权(6)

⭐⭐ 小程序专栏&#xff1a;小程序开发专栏 ⭐⭐ 个人主页&#xff1a;个人主页 目录 一.了解微信授权登录 小程序登录授权基本原理&#xff1a; 二.微信授权登录演示 三.微信授权与后端的交互 3.1后台代码&#xff1a; 3.2 前端代码&#xff1a; 四.微信退出 五.微信表情包…

DELM深度极限学习机回归预测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

自然语言处理---Self Attention自注意力机制

Self-attention介绍 Self-attention是一种特殊的attention&#xff0c;是应用在transformer中最重要的结构之一。attention机制&#xff0c;它能够帮助找到子序列和全局的attention的关系&#xff0c;也就是找到权重值wi。Self-attention相对于attention的变化&#xff0c;其实…

项目总结-商品购买流程

&#xff08;1&#xff09;添加购物车 Controller&#xff1a; CartService&#xff1a; 实现类&#xff1a; CartDetail detaildao.queryByCdid(cid,gds.getId()); CartDao&#xff1a; //获取详情对象Select("select * from t_cartdetail where cid#{cid} and gid#{gid…

buu第五页 wp

[RootersCTF2019]babyWeb 预期解 一眼就是sql注入&#xff0c;发现过滤了 UNION SLEEP " OR - BENCHMARK盲注没法用了&#xff0c;因为union被过滤&#xff0c;堆叠注入也不考虑&#xff0c;发现报错有回显&#xff0c;尝试报错注入。 尝试&#xff1a; 1||(updatex…

ubuntu20.04下安装nc

前言 nc在网络渗透测试中非常好用&#xff0c;这里的主要记一下Ubuntu20.04中nc的安装 编译安装 第一种方式是自己编译安装&#xff0c;先下载安装包 nc.zip wget http://sourceforge.net/projects/netcat/files/netcat/0.7.1/netcat-0.7.1.tar.gz/download -O netcat-0.7.…

anyproxy 的安装和抓包使用

简介 AnyProxy是阿里开发的开源的代理服务器&#xff0c;主要特性包括&#xff1a; 基于Node.js&#xff0c;开放二次开发能力&#xff0c;允许自定义请求处理逻辑支持Https的解析提供GUI界面&#xff0c;用以观察请求 安装运行Anyproxy 首先需要电脑由安装 node&#xff0…