乐趣区

关于后端:Java-不可变集合-Stream流以及方法引用

1. 不可变汇合

1.1 什么是不可变汇合

​ 是一个长度不可变,内容也无奈批改的汇合

1.2 应用场景

​ 如果某个数据不能被批改,把它防御性地拷贝到不可变汇合中是个很好的实际。

​ 当汇合对象被不可信的库调用时,不可变模式是平安的。

简略了解:

​ 不想让他人批改汇合中的内容

比如说:

1,斗地主的 54 张牌,是不能增加,不能删除,不能批改的

2,斗地主的打牌规定:单张,对子,三张,顺子等,也是不能批改的

3,用代码获取的操作系统硬件信息,也是不能被批改的

1.3 不可变汇合分类

  • 不可变的 list 汇合
  • 不可变的 set 汇合
  • 不可变的 map 汇合

1.4 不可变的 list 汇合

public class ImmutableDemo1 {public static void main(String[] args) {
        /*
            创立不可变的 List 汇合
            "张三", "李四", "王五", "赵六"
        */

        // 一旦创立结束之后,是无奈进行批改的,在上面的代码中,只能进行查问操作
        List<String> list = List.of("张三", "李四", "王五", "赵六");

        System.out.println(list.get(0));
        System.out.println(list.get(1));
        System.out.println(list.get(2));
        System.out.println(list.get(3));

        System.out.println("---------------------------");

        for (String s : list) {System.out.println(s);
        }

        System.out.println("---------------------------");


        Iterator<String> it = list.iterator();
        while(it.hasNext()){String s = it.next();
            System.out.println(s);
        }
        System.out.println("---------------------------");

        for (int i = 0; i < list.size(); i++) {String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("---------------------------");

        //list.remove("李四");
        //list.add("aaa");
        list.set(0,"aaa");
    }
}

1.5 不可变的 Set 汇合

public class ImmutableDemo2 {public static void main(String[] args) {
        /*
           创立不可变的 Set 汇合
           "张三", "李四", "王五", "赵六"


           细节:当咱们要获取一个不可变的 Set 汇合时,外面的参数肯定要保障唯一性
        */

        // 一旦创立结束之后,是无奈进行批改的,在上面的代码中,只能进行查问操作
        Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");

        for (String s : set) {System.out.println(s);
        }

        System.out.println("-----------------------");

        Iterator<String> it = set.iterator();
        while(it.hasNext()){String s = it.next();
            System.out.println(s);
        }

        System.out.println("-----------------------");
        //set.remove("王五");
    }
}

1.6 不可变的 Map 汇合

1.6.1:键值对个数小于等于 10

public class ImmutableDemo3 {public static void main(String[] args) {
       /*
        创立 Map 的不可变汇合
            细节 1:键是不能反复的
            细节 2:Map 外面的 of 办法,参数是有下限的,最多只能传递 20 个参数,10 个键值对
            细节 3:如果咱们要传递多个键值对对象,数量大于 10 个,在 Map 接口中还有一个办法
        */

        // 一旦创立结束之后,是无奈进行批改的,在上面的代码中,只能进行查问操作
        Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海",
                "赵六", "广州", "孙七", "深圳", "周八", "杭州",
                "吴九", "宁波", "郑十", "苏州", "刘一", "无锡",
                "陈二", "嘉兴");

        Set<String> keys = map.keySet();
        for (String key : keys) {String value = map.get(key);
            System.out.println(key + "=" + value);
        }

        System.out.println("--------------------------");

        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }
        System.out.println("--------------------------");
    }
}

1.6.2:键值对个数大于 10

public class ImmutableDemo4 {public static void main(String[] args) {

        /*
            创立 Map 的不可变汇合, 键值对的数量超过 10 个
        */

        //1. 创立一个一般的 Map 汇合
        HashMap<String, String> hm = new HashMap<>();
        hm.put("张三", "南京");
        hm.put("李四", "北京");
        hm.put("王五", "上海");
        hm.put("赵六", "北京");
        hm.put("孙七", "深圳");
        hm.put("周八", "杭州");
        hm.put("吴九", "宁波");
        hm.put("郑十", "苏州");
        hm.put("刘一", "无锡");
        hm.put("陈二", "嘉兴");
        hm.put("aaa", "111");

        //2. 利用下面的数据来获取一个不可变的汇合
/*
        // 获取到所有的键值对对象(Entry 对象)Set<Map.Entry<String, String>> entries = hm.entrySet();
        // 把 entries 变成一个数组
        Map.Entry[] arr1 = new Map.Entry[0];
        //toArray 办法在底层会比拟汇合的长度跟数组的长度两者的大小
        // 如果汇合的长度 > 数组的长度:数据在数组中放不下,此时会依据理论数据的个数,从新创立数组
        // 如果汇合的长度 <= 数组的长度:数据在数组中放的下,此时不会创立新的数组,而是间接用
        Map.Entry[] arr2 = entries.toArray(arr1);
        // 不可变的 map 汇合
        Map map = Map.ofEntries(arr2);
        map.put("bbb","222");*/


        //Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));

        Map<String, String> map = Map.copyOf(hm);
        map.put("bbb","222");
    }
}

2.Stream 流

2.1 体验 Stream 流

  • 案例需要

    依照上面的要求实现汇合的创立和遍历

    • 创立一个汇合,存储多个字符串元素
    • 把汇合中所有以 ” 张 ” 结尾的元素存储到一个新的汇合
    • 把 ” 张 ” 结尾的汇合中的长度为 3 的元素存储到一个新的汇合
    • 遍历上一步失去的汇合
  • 原始形式示例代码

    public class MyStream1 {public static void main(String[] args) {
            // 汇合的批量增加
            ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
            //list.add()
    
            // 遍历 list1 把以张结尾的元素增加到 list2 中。ArrayList<String> list2 = new ArrayList<>();
            for (String s : list1) {if(s.startsWith("张")){list2.add(s);
                }
            }
            // 遍历 list2 汇合,把其中长度为 3 的元素,再增加到 list3 中。ArrayList<String> list3 = new ArrayList<>();
            for (String s : list2) {if(s.length() == 3){list3.add(s);
                }
            }
            for (String s : list3) {System.out.println(s);
            }      
        }
    }
  • 应用 Stream 流示例代码

    public class StreamDemo {public static void main(String[] args) {
            // 汇合的批量增加
            ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
    
            //Stream 流
            list1.stream().filter(s->s.startsWith("张"))
                    .filter(s->s.length() == 3)
                    .forEach(s-> System.out.println(s));
        }
    }
  • Stream 流的益处

    • 间接浏览代码的字面意思即可完满展现无关逻辑形式的语义:获取流、过滤姓张、过滤长度为 3、逐个打印
    • Stream 流把真正的函数式编程格调引入到 Java 中
    • 代码简洁

2.2Stream 流的常见生成形式

  • Stream 流的思维
  • Stream 流的三类办法

    • 获取 Stream 流

      • 创立一条流水线, 并把数据放到流水线上筹备进行操作
    • 两头办法

      • 流水线上的操作
      • 一次操作结束之后, 还能够持续进行其余操作
    • 终结办法

      • 一个 Stream 流只能有一个终结办法
      • 是流水线上的最初一个操作
  • 生成 Stream 流的形式

    • Collection 体系汇合

      应用默认办法 stream() 生成流,default Stream<E> stream()

    • Map 体系汇合

      把 Map 转成 Set 汇合,间接的生成流

    • 数组

      通过 Arrays 中的静态方法 stream 生成流

    • 同种数据类型的多个数据

      通过 Stream 接口的静态方法 of(T… values) 生成流

  • 代码演示

    public class StreamDemo {public static void main(String[] args) {//Collection 体系的汇合能够应用默认办法 stream() 生成流
            List<String> list = new ArrayList<String>();
            Stream<String> listStream = list.stream();
    
            Set<String> set = new HashSet<String>();
            Stream<String> setStream = set.stream();
    
            //Map 体系的汇合间接的生成流
            Map<String,Integer> map = new HashMap<String, Integer>();
            Stream<String> keyStream = map.keySet().stream();
            Stream<Integer> valueStream = map.values().stream();
            Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
    
            // 数组能够通过 Arrays 中的静态方法 stream 生成流
            String[] strArray = {"hello","world","java"};
            Stream<String> strArrayStream = Arrays.stream(strArray);
          
              // 同种数据类型的多个数据能够通过 Stream 接口的静态方法 of(T... values) 生成流
            Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
            Stream<Integer> intStream = Stream.of(10, 20, 30);
        }
    }

2.3Stream 流两头操作方法

  • 概念

    两头操作的意思是, 执行完此办法之后,Stream 流仍然能够继续执行其余操作

  • 常见办法

    办法名 阐明
    Stream<T> filter(Predicate predicate) 用于对流中的数据进行过滤
    Stream<T> limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据
    Stream<T> skip(long n) 跳过指定参数个数的数据,返回由该流的残余元素组成的流
    static <T> Stream<T> concat(Stream a, Stream b) 合并 a 和 b 两个流为一个流
    Stream<T> distinct() 返回由该流的不同元素(依据 Object.equals(Object))组成的流
  • filter 代码演示

    public class MyStream3 {public static void main(String[] args) {//        Stream<T> filter(Predicate predicate):过滤
    //        Predicate 接口中的办法    boolean test(T t):对给定的参数进行判断,返回一个布尔值
    
            ArrayList<String> list = new ArrayList<>();
            list.add("张三丰");
            list.add("张无忌");
            list.add("张翠山");
            list.add("王二麻子");
            list.add("张良");
            list.add("谢广坤");
    
            //filter 办法获取流中的 每一个数据.
            // 而 test 办法中的 s, 就顺次示意流中的每一个数据.
            // 咱们只有在 test 办法中对 s 进行判断就能够了.
            // 如果判断的后果为 true, 则以后的数据留下
            // 如果判断的后果为 false, 则以后数据就不要.
    //        list.stream().filter(//                new Predicate<String>() {
    //                    @Override
    //                    public boolean test(String s) {//                        boolean result = s.startsWith("张");
    //                        return result;
    //                    }
    //                }
    //        ).forEach(s-> System.out.println(s));
    
            // 因为 Predicate 接口中只有一个形象办法 test
            // 所以咱们能够应用 lambda 表达式来简化
    //        list.stream().filter(//                (String s)->{//                    boolean result = s.startsWith("张");
    //                        return result;
    //                }
    //        ).forEach(s-> System.out.println(s));
    
            list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));
    
        }
    }
  • limit&skip 代码演示

    public class StreamDemo02 {public static void main(String[] args) {
            // 创立一个汇合,存储多个字符串元素
            ArrayList<String> list = new ArrayList<String>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            // 需要 1:取前 3 个数据在控制台输入
            list.stream().limit(3).forEach(s-> System.out.println(s));
            System.out.println("--------");
    
            // 需要 2:跳过 3 个元素,把剩下的元素在控制台输入
            list.stream().skip(3).forEach(s-> System.out.println(s));
            System.out.println("--------");
    
            // 需要 3:跳过 2 个元素,把剩下的元素中前 2 个在控制台输入
            list.stream().skip(2).limit(2).forEach(s-> System.out.println(s));
        }
    }
  • concat&distinct 代码演示

    public class StreamDemo03 {public static void main(String[] args) {
            // 创立一个汇合,存储多个字符串元素
            ArrayList<String> list = new ArrayList<String>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            // 需要 1:取前 4 个数据组成一个流
            Stream<String> s1 = list.stream().limit(4);
    
            // 需要 2:跳过 2 个数据组成一个流
            Stream<String> s2 = list.stream().skip(2);
    
            // 需要 3:合并需要 1 和需要 2 失去的流,并把后果在控制台输入
    //        Stream.concat(s1,s2).forEach(s-> System.out.println(s));
    
            // 需要 4:合并需要 1 和需要 2 失去的流,并把后果在控制台输入,要求字符串元素不能反复
            Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));
        }
    }

2.4Stream 流终结操作方法

  • 概念

    终结操作的意思是, 执行完此办法之后,Stream 流将不能再执行其余操作

  • 常见办法

    办法名 阐明
    void forEach(Consumer action) 对此流的每个元素执行操作
    long count() 返回此流中的元素数
  • 代码演示

    public class MyStream5 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();
            list.add("张三丰");
            list.add("张无忌");
            list.add("张翠山");
            list.add("王二麻子");
            list.add("张良");
            list.add("谢广坤");
    
            //method1(list);
            
    //        long count():返回此流中的元素数
            long count = list.stream().count();
            System.out.println(count);
        }
    
        private static void method1(ArrayList<String> list) {//  void forEach(Consumer action):对此流的每个元素执行操作
            //  Consumer 接口中的办法 void accept(T t):对给定的参数执行此操作
            // 在 forEach 办法的底层, 会循环获取到流中的每一个数据.
            // 并循环调用 accept 办法, 并把每一个数据传递给 accept 办法
            // s 就顺次示意了流中的每一个数据.
            // 所以, 咱们只有在 accept 办法中, 写上解决的业务逻辑就能够了.
            list.stream().forEach(new Consumer<String>() {
                        @Override
                        public void accept(String s) {System.out.println(s);
                        }
                    }
            );
          
            System.out.println("====================");
            //lambda 表达式的简化格局
            // 是因为 Consumer 接口中, 只有一个 accept 办法
            list.stream().forEach((String s)->{System.out.println(s);
                    }
            );
            System.out.println("====================");
            //lambda 表达式还是能够进一步简化的.
            list.stream().forEach(s->System.out.println(s));
        }
    }

2.5Stream 流的收集操作

  • 概念

    对数据应用 Stream 流的形式操作结束后, 能够把流中的数据收集到汇合中

  • 罕用办法

    办法名 阐明
    R collect(Collector collector) 把后果收集到汇合中
  • 工具类 Collectors 提供了具体的收集形式

    办法名 阐明
    public static <T> Collector toList() 把元素收集到 List 汇合中
    public static <T> Collector toSet() 把元素收集到 Set 汇合中
    public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到 Map 汇合中
  • 代码演示

    // toList 和 toSet 办法演示 
    public class MyStream7 {public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();
            for (int i = 1; i <= 10; i++) {list1.add(i);
            }
    
            list1.add(10);
            list1.add(10);
            list1.add(10);
            list1.add(10);
            list1.add(10);
    
            //filter 负责过滤数据的.
            //collect 负责收集数据.
                    // 获取流中残余的数据, 然而他不负责创立容器, 也不负责把数据增加到容器中.
            //Collectors.toList() : 在底层会创立一个 List 汇合. 并把所有的数据增加到 List 汇合中.
            List<Integer> list = list1.stream().filter(number -> number % 2 == 0)
                    .collect(Collectors.toList());
    
            System.out.println(list);
    
        Set<Integer> set = list1.stream().filter(number -> number % 2 == 0)
                .collect(Collectors.toSet());
        System.out.println(set);
    }
    }
    /**
    Stream 流的收集办法 toMap 办法演示
    创立一个 ArrayList 汇合,并增加以下字符串。字符串中后面是姓名,前面是年龄
    "zhangsan,23"
    "lisi,24"
    "wangwu,25"
    保留年龄大于等于 24 岁的人,并将后果收集到 Map 汇合中,姓名为键,年龄为值
    */
    public class MyStream8 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();
            list.add("zhangsan,23");
            list.add("lisi,24");
            list.add("wangwu,25");
    
            Map<String, Integer> map = list.stream().filter(
                    s -> {String[] split = s.split(",");
                        int age = Integer.parseInt(split[1]);
                        return age >= 24;
                    }
    
             //   collect 办法只能获取到流中残余的每一个数据.
             // 在底层不能创立容器, 也不能把数据增加到容器当中
    
             //Collectors.toMap 创立一个 map 汇合并将数据增加到汇合当中
    
              // s 顺次示意流中的每一个数据
    
              // 第一个 lambda 表达式就是如何获取到 Map 中的键
              // 第二个 lambda 表达式就是如何获取 Map 中的值
            ).collect(Collectors.toMap(s -> s.split(",")[0],
                    s -> Integer.parseInt(s.split(",")[1]) ));
    
            System.out.println(map);
        }
    }

2.6Stream 流综合练习

  • 案例需要

    当初有两个 ArrayList 汇合,别离存储 6 名男演员名称和 6 名女演员名称,要求实现如下的操作

    • 男演员只有名字为 3 个字的前三人
    • 女演员只有姓林的,并且不要第一个
    • 把过滤后的男演员姓名和女演员姓名合并到一起
    • 把上一步操作后的元素作为构造方法的参数创立演员对象, 遍历数据

    演员类 Actor 曾经提供,外面有一个成员变量,一个带参构造方法,以及成员变量对应的 get/set 办法

  • 代码实现

    演员类

    public class Actor {
        private String name;
    
        public Actor(String name) {this.name = name;}
    
        public String getName() {return name;}
    
        public void setName(String name) {this.name = name;}
    }

    测试类

    public class StreamTest {public static void main(String[] args) {
            // 创立汇合
            ArrayList<String> manList = new ArrayList<String>();
            manList.add("周润发");
            manList.add("成龙");
            manList.add("刘德华");
            manList.add("吴京");
            manList.add("周星驰");
            manList.add("李连杰");
      
            ArrayList<String> womanList = new ArrayList<String>();
            womanList.add("林心如");
            womanList.add("张曼玉");
            womanList.add("林青霞");
            womanList.add("柳岩");
            womanList.add("林志玲");
            womanList.add("王祖贤");
      
            // 男演员只有名字为 3 个字的前三人
            Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
      
            // 女演员只有姓林的,并且不要第一个
            Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
      
            // 把过滤后的男演员姓名和女演员姓名合并到一起
            Stream<String> stream = Stream.concat(manStream, womanStream);
      
              // 将流中的数据封装成 Actor 对象之后打印
              stream.forEach(name -> {Actor actor = new Actor(name);
                System.out.println(actor);
            }); 
        }
    }

3. 办法援用

3.1 体验办法援用

  • 办法援用的呈现起因

    在应用 Lambda 表达式的时候,咱们实际上传递进去的代码就是一种解决方案:拿参数做操作

    那么思考一种状况:如果咱们在 Lambda 中所指定的操作计划,曾经有中央存在雷同计划,那是否还有必要再写反复逻辑呢?答案必定是没有必要

    那咱们又是如何应用曾经存在的计划的呢?

    这就是咱们要解说的办法援用,咱们是通过办法援用来应用曾经存在的计划

  • 代码演示

    public interface Printable {void printString(String s);
    }
    
    public class PrintableDemo {public static void main(String[] args) {
            // 在主办法中调用 usePrintable 办法
    //        usePrintable((String s) -> {//            System.out.println(s);
    //        });
            //Lambda 简化写法
            usePrintable(s -> System.out.println(s));
    
            // 办法援用
            usePrintable(System.out::println);
    
        }
    
        private static void usePrintable(Printable p) {p.printString("爱生存爱 Java");
        }
    }
    

3.2 办法援用符

  • 办法援用符

    :: 该符号为援用运算符,而它所在的表达式被称为办法援用

  • 推导与省略

    • 如果应用 Lambda,那么依据“可推导就是可省略”的准则,无需指定参数类型,也无需指定的重载模式,它们都将被主动推导
    • 如果应用办法援用,也是同样能够依据上下文进行推导
    • 办法援用是 Lambda 的孪生兄弟

3.3 援用类办法

​ 援用类办法,其实就是援用类的静态方法

  • 格局

    类名:: 静态方法

  • 范例

    Integer::parseInt

    Integer 类的办法:public static int parseInt(String s) 将此 String 转换为 int 类型数据

  • 练习形容

    • 定义一个接口 (Converter),外面定义一个形象办法 int convert(String s);
    • 定义一个测试类 (ConverterDemo),在测试类中提供两个办法

      • 一个办法是:useConverter(Converter c)
      • 一个办法是主办法,在主办法中调用 useConverter 办法
  • 代码演示

    public interface Converter {int convert(String s);
    }
    
    public class ConverterDemo {public static void main(String[] args) {
    
            //Lambda 写法
            useConverter(s -> Integer.parseInt(s));
    
            // 援用类办法
            useConverter(Integer::parseInt);
    
        }
    
        private static void useConverter(Converter c) {int number = c.convert("666");
            System.out.println(number);
        }
    }
  • 应用阐明

    Lambda 表达式被类办法代替的时候,它的形式参数全副传递给静态方法作为参数

3.4 援用对象的实例办法

​ 援用对象的实例办法,其实就援用类中的成员办法

  • 格局

    对象:: 成员办法

  • 范例

    “HelloWorld”::toUpperCase

    String 类中的办法:public String toUpperCase() 将此 String 所有字符转换为大写

  • 练习形容

    • 定义一个类 (PrintString),外面定义一个办法

      public void printUpper(String s):把字符串参数变成大写的数据,而后在控制台输入

    • 定义一个接口 (Printer),外面定义一个形象办法

      void printUpperCase(String s)

    • 定义一个测试类 (PrinterDemo),在测试类中提供两个办法

      • 一个办法是:usePrinter(Printer p)
      • 一个办法是主办法,在主办法中调用 usePrinter 办法
  • 代码演示

    public class PrintString {
        // 把字符串参数变成大写的数据,而后在控制台输入
        public void printUpper(String s) {String result = s.toUpperCase();
            System.out.println(result);
        }
    }
    
    public interface Printer {void printUpperCase(String s);
    }
    
    public class PrinterDemo {public static void main(String[] args) {
    
            //Lambda 简化写法
            usePrinter(s -> System.out.println(s.toUpperCase()));
    
            // 援用对象的实例办法
            PrintString ps = new PrintString();
            usePrinter(ps::printUpper);
    
        }
    
        private static void usePrinter(Printer p) {p.printUpperCase("HelloWorld");
        }
    }
    
  • 应用阐明

    Lambda 表达式被对象的实例办法代替的时候,它的形式参数全副传递给该办法作为参数

3.5 援用类的实例办法

​ 援用类的实例办法,其实就是援用类中的成员办法

  • 格局

    类名:: 成员办法

  • 范例

    String::substring

    public String substring(int beginIndex,int endIndex)

    从 beginIndex 开始到 endIndex 完结,截取字符串。返回一个子串,子串的长度为 endIndex-beginIndex

  • 练习形容

    • 定义一个接口 (MyString),外面定义一个形象办法:

      String mySubString(String s,int x,int y);

    • 定义一个测试类 (MyStringDemo),在测试类中提供两个办法

      • 一个办法是:useMyString(MyString my)
      • 一个办法是主办法,在主办法中调用 useMyString 办法
  • 代码演示

    public interface MyString {String mySubString(String s,int x,int y);
    }
    
    public class MyStringDemo {public static void main(String[] args) {
            //Lambda 简化写法
            useMyString((s,x,y) -> s.substring(x,y));
    
            // 援用类的实例办法
            useMyString(String::substring);
    
        }
    
        private static void useMyString(MyString my) {String s = my.mySubString("HelloWorld", 2, 5);
            System.out.println(s);
        }
    }
  • 应用阐明

    ​ Lambda 表达式被类的实例办法代替的时候
    ​ 第一个参数作为调用者
    ​ 前面的参数全副传递给该办法作为参数

3.6 援用结构器

​ 援用结构器,其实就是援用构造方法

  • l 格局

    类名::new

  • 范例

    Student::new

  • 练习形容

    • 定义一个类 (Student),外面有两个成员变量 (name,age)

      并提供无参构造方法和带参构造方法,以及成员变量对应的 get 和 set 办法

    • 定义一个接口 (StudentBuilder),外面定义一个形象办法

      Student build(String name,int age);

    • 定义一个测试类 (StudentDemo),在测试类中提供两个办法

      • 一个办法是:useStudentBuilder(StudentBuilder s)
      • 一个办法是主办法,在主办法中调用 useStudentBuilder 办法
  • 代码演示

    public class Student {
        private String name;
        private int age;
    
        public Student() {}
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {return name;}
    
        public void setName(String name) {this.name = name;}
    
        public int getAge() {return age;}
    
        public void setAge(int age) {this.age = age;}
    }
    
    public interface StudentBuilder {Student build(String name,int age);
    }
    
    public class StudentDemo {public static void main(String[] args) {
    
            //Lambda 简化写法
            useStudentBuilder((name,age) -> new Student(name,age));
    
            // 援用结构器
            useStudentBuilder(Student::new);
    
        }
    
        private static void useStudentBuilder(StudentBuilder sb) {Student s = sb.build("林青霞", 30);
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
  • 应用阐明

    Lambda 表达式被结构器代替的时候,它的形式参数全副传递给结构器作为参数

退出移动版