day20


Lambda表达式 & 枚举

新特性1:Lambda表达式概述

  • JDK1.8开始引入Lambda表达式,支持函数式编程。
  • 函数式编程可以避免面向对象编程中的一些繁琐问题。
  • Lambda表达式是双刃剑,简化代码但可能降低可读性。

写Lambda表达式的场景

  • 必须有函数接口(只有一个抽象方法的接口)。
  • 依赖于类型推断机制,编译器可以根据上下文推断参数类型。

Lambda表达式的优点

  • 匿名函数,可以传递代码。
  • 代码更简洁、灵活。
  • 提升了Java的语言表达能力。

Lambda基本语法

  • 使用->操作符,分为参数列表和Lambda体。
  • 参数列表对应接口中的形参,Lambda体对应方法体。

Lambda表达式分类

  1. 无参数,无返回值
  2. 有一个参数,无返回值
  3. 单个参数时,可以省略小括号
  4. 两个以上参数,有返回值,多条语句
  5. 单条语句时,可以省略return和大括号
  6. 参数类型可以省略,由编译器推断

Java内置函数式接口

  • Predicate:断言型接口,boolean test(T t); 传T类型的参数返回boolean值
  • Function<T,R>:函数型接口,R apply(T t); 传T类型的参数返回T类型的值
  • Supplier:供给型接口,T get(); 无参返回T类型的值
  • Consumer:消费型接口,void accept(T t); 传T类型的参数不返回

Lambda用法再简洁之方法引用

  • 对象引用对象引用::实例方法名
  • 类名::静态方法名
  • 类名::实例方法名
  • 构造方法引用类名::new
  • 数组引用元素类型[]::new

误区

  • Lambda表达式不是匿名内部类,而是通过invokedynamic指令调用。

小结

  • 优点:减少代码量,节省内存。
  • 缺点:可读性差,不易调试。

新特性2 枚举

枚举概述

  • 枚举类型用于管理有限常量数据。
  • 提高代码可读性和简洁性。

JDK1.5之前使用枚举

  • 创建枚举类的属性,必须是私有常量。
  • 构造方法私有化。
  • 提供公共静态方法获取枚举对象。
  • 提供公共方法获取属性。
  • 重写toString()方法。

JDK1.5之后使用枚举

  • 枚举对象放在开头。
  • 枚举类属性为私有常量。
  • 构造方法私有化。
  • 提供公共方法获取属性。
  • 重写toString()方法。

枚举类实现接口

  • 枚举可以单独实现接口。

lambda代码示例

断言型接口使用

public class test6 {
    private static final List<Staff> list = Arrays.asList(
            new Staff("李刚", 18, 35000),
            new Staff("钱志强", 13, 20000),
            new Staff("江川", 24, 50000),
            new Staff("祝帅", 16, 21000),
            new Staff("吴问强", 8, 8000)
    );

    public static void main(String[] args) {
        //这里的s代表传入Predicate接口方法的参数,后面是s.getSalary()>10000的返回值
        panduan(list,s->s.getSalary()>10000);
    }

    public static void panduan(List<Staff> list,Predicate<Staff> predicate){
        ArrayList<Staff> list2 = new ArrayList<>();
        for (Staff s : list) {
            if(predicate.test(s)) {
                list2.add(s);
            }
        }
        for (Staff staff : list2) {
            System.out.println(staff);

        }

    }
}

函数型接口及构造方法简化实例

package com.shujia.day20;

import java.util.function.Function;

class test1{
    private String naem;

    public test1(String naem) {
        this.naem = naem;
    }

    public String getNaem() {
        return naem;
    }

    public void setNaem(String naem) {
        this.naem = naem;
    }

    @Override
    public String toString() {
        return "test1{" +
                "naem='" + naem + '\'' +
                '}';
    }
}

public class test5 {

    public static void main(String[] args) {

        show(s->new test1(s));
        //变量->new 类名(变量) 当变量一致时可以缩写成 类名::new
        show(test1::new);
    }

    //函数型接口
    public static void show(Function<String,test1> function){
        System.out.println(function.apply("李刚"));
    }
}

供给型接口实例

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;

/*
    java内置函数式接口:供给型接口
    只有函数式接口【有且仅有一个抽象方法】才可以被@FunctionalInterface注解所修饰
    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }

 */
public class Demo {
    public static void main(String[] args) {
        //随机生成10个1-100的数据到集合返回
        List<Integer> list = getList(() -> new Random().nextInt(100) + 1);
        for (Integer i : list) {
            System.out.println(i);
        }

    }

    public static List<Integer> getList(Supplier<Integer> supplier){
        ArrayList<Integer> list = new ArrayList<>();
        for(int i=1;i<11;i++){
            list.add(supplier.get());
        }
        return list;
    }


}

消费型接口实例

import java.util.function.Consumer;

/*
    java内置函数式接口:消费型接口
    只有函数式接口【有且仅有一个抽象方法】才可以被@FunctionalInterface注解所修饰
    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
    }
 */
public class Demo {
    public static void main(String[] args) {
        Staff s = new Staff("sj1001", "李刚", 18, 35000);
        fun1(s, liGang -> System.out.println("员工编号:" + liGang.getId() + ", 姓名:" + liGang.getName() + ", 年龄:" + liGang.getAge() + ", 薪资:" + liGang.getSalary()));
    }

    public static void fun1(Staff staff, Consumer<Staff> consumer) {
        consumer.accept(staff);
    }
}

类简洁用法

//        List<Staff> staffList = fun1(staffs -> Arrays.asList(staffs), s1, s2, s3, s4, s5);
        /**
         *  假如 Lambda 表达式符合如下格式:
         *      ([变量1, 变量2, ...]) -> 类名.静态方法名([变量1, 变量2, ...])
         * 我们可以简写成如下格式:
         *      类名::静态方法名
         */
        List<Staff> staffList = fun1(Arrays::asList, s1, s2, s3, s4, s5);

对象引用

/**
 * 假如 Lambda 表达式符合如下格式:
 * ([变量1, 变量2, ...]) -> 对象引用.方法名([变量1, 变量2, ...])
 * 我们可以简写成如下格式:
 * 对象引用::方法名
 */
show2("hello","ligang",(s1,s2)->demo2.show(s1,s2));
        show2("hello","ligang",demo2::show);

数组引用

interface Inter{
    int[] fun(int i);
}

package com.shujia.day20;

枚举

/*
    1. 创建枚举类的属性(成员遍历),必须是作为私有常量出现
    2. 必须将构造方法私有化,这是为了保证类的对象是有限个的目的
    3. 提供公共的静态的final方法给外界获取枚举类中多个对象
    4. 提供公共的获取属性的方法
    5. 重写toString()方法

 */
class Season{
    //1. 创建枚举类的属性(成员遍历),必须是作为私有常量出现
    private String name;
    private String info;

    //2. 必须将构造方法私有化,这是为了保证类的对象是有限个的目的
    private Season(String name, String info){
        this.name = name;
        this.info = info;
    }

    //3. 提供公共的静态的final方法给外界获取枚举类中多个对象
    public static final Season SPRING = new Season("春天","春暖花开");
    public static final Season SUMMER = new Season("夏天","烈日炎炎");
    public static final Season AUTUMN = new Season("秋天","秋高气爽");
    public static final Season WINTER = new Season("冬天","白雪皑皑");

    //4. 提供公共的获取属性的方法


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", info='" + info + '\'' +
                '}';
    }
}

public class SeasonDemo1 {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        Season summer = Season.SUMMER;

    }
}

public class Demo {
    public static void main(String[] args) {
//        show(7, i->new int[i]);

        /**
         *  假如我们的 Lambda 表达式符合如下格式:
         *      (变量) -> new 元素类型[变量]
         * 我们就可以简写成如下格式:
         *      元素类型[] :: new
         */
        show(7, int[]::new);
    }
    public static void show(int i,Inter inter){
        int[] ints = inter.fun(i);
        System.out.println(ints.length);
    }
}
package com.shujia.day20;

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

public class StudentDemo {
    public static void main(String[] args) throws Exception{
        //通过反射获取一个class文件对应Class对象
        //方式1:在已经有对象的前提下获取
//        Student student = new Student();
//        Class<? extends Student> c1 = student.getClass();
//        Class<? extends Student> c2 = student.getClass();
//        System.out.println(c1==c2);

        //方式2:可以直接通过类名的方式获取
//        Class<Student> c1 = Student.class;
//        Class<Student> c2 = Student.class;
//        System.out.println(c1==c2);

        //方式3:Class.forName()
        Class<?> c1 = Class.forName("com.shujia.day20.Student");
//        Class<?> c2 = Class.forName("com.shujia.day20.Student");
//        System.out.println(c1==c2);

        // 获取类中的构造方法并使用
        // getConstructor() 只能获取某一个公共构造方法
        // public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor<?> cons1 = c1.getConstructor();
//        System.out.println(cons1);
//        Constructor<?> cons2 = c1.getConstructor(String.class,String.class);
//        System.out.println(cons2);
        Constructor<?> cons2 = c1.getDeclaredConstructor(String.class, String.class);
        System.out.println(cons2);
        Constructor<?> cons3 = c1.getDeclaredConstructor(String.class);
        System.out.println(cons3);
        //如何使用获取到的构造方法呢?
        //public T newInstance(Object ... initargs)
        Object o = cons1.newInstance();
        System.out.println(o);
        cons3.setAccessible(true);
        Object o1 = cons3.newInstance("1001");
        System.out.println(o1);

        // 获取类中的成员变量并使用
        //getField 只能获取公共的成员变量
        Field like = c1.getField("like");
//        Field id = c1.getField("id");
        Field id = c1.getDeclaredField("id");
        // 给对象o1中成员变量like进行赋值操作
        like.set(o1, "骑自行车");
        System.out.println(o1);
        id.setAccessible(true);
        id.set(o1,"1002");
        System.out.println(o1);

        // 获取类中的成员放啊并使用
        Method fun1 = c1.getMethod("fun1");
        System.out.println(fun1);
        Method fun11 = c1.getMethod("fun1",String.class);
        System.out.println(fun11);
//        Method fun3 = c1.getMethod("fun3");
//        System.out.println(fun3);
        Method fun3 = c1.getDeclaredMethod("fun3");
        System.out.println(fun3);
        //使用成员方法
        fun1.invoke(o1);
        fun3.setAccessible(true);
        fun3.invoke(o1);

    }
}
posted @   先瞄准再开枪  阅读(10)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示