Java8 教程

Java8 Lambda 构造器引用

在Java 8中,构造器引用是一种特殊的方法引用,用于引用构造函数。它允许您使用 “::” 操作符来引用一个构造函数,而不是调用它。构造器引用的语法如下:

ClassName::new

其中,ClassName 是要引用的类的名称,后面跟着 :: 操作符和关键字 new。这种语法可以用来创建一个对构造函数的引用,而不实际调用它,从而可以将构造函数作为方法引用传递给函数式接口。

下面将分别介绍如何引用类中仅仅拥有一个构造方法、多个构造方法和数组。

单参数构造方法

构造器引用同方法引用类似,不同的是在构造器引用中方法名是 new。例如,Button::new 表示 Button 类的构造器引用。

package com.hxstrive.jdk8.constructor_ref;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* 构造器引用
* @author hxstrive.com
*/
public class ConstructorRef01 {

   public static void main(String[] args) {
       List<ConstructorRef01.User> userList = Stream.of("Tom", "Helen")
               .map(ConstructorRef01.User::new)
               .collect(Collectors.toList());
       for(ConstructorRef01.User user : userList) {
           System.out.println(user);
       }
   }

   static class User {
       private String name;

       public User(String name) {
           this.name = name;
       }

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

}

运行示例,输出如下:

User{name='Tom'}
User{name='Helen'}

多构造方法

对于拥有多个构造器的类,选择使用哪个构造器取决于上下文。假设你有一个字符串列表和一个数字列表,分别通过这两个列表去构建 ConstructorRef02.User 对象,使用如下表达式:

package com.hxstrive.jdk8.constructor_ref;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* 构造器引用,根据上下文自动选择合适的构造器
* @author hxstrive.com
*/
public class ConstructorRef02 {

   public static void main(String[] args) {
       List<ConstructorRef02.User> userList = Stream.of("Tom", "Helen")
               .map(ConstructorRef02.User::new)
               .collect(Collectors.toList());
       for(ConstructorRef02.User user : userList) {
           System.out.println(user);
       }

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

       userList = Stream.of(100, 200)
               .map(ConstructorRef02.User::new)
               .collect(Collectors.toList());
       for(ConstructorRef02.User user : userList) {
           System.out.println(user);
       }
   }

   static class User {
       private int id;
       private String name;

       // 构造方法1
       public User(int id, String name) {
           this.id = id;
           this.name = name;
       }

       // 构造方法2
       public User(int id) {
           this.id = id;
       }

       // 构造方法3
       public User(String name) {
           this.name = name;
       }

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

}

运行示例,输出如下:

User{id=0, name='Tom'}
User{id=0, name='Helen'}
======================================
User{id=100, name='null'}
User{id=200, name='null'}

数组构造器引用

我们还可以使用数组类型来编写构造器引用。例如,String[]::new 是一个含有一个参数的构造器引用,这个参数就是数组的长度。它等同于 Lambda 表达式 x->new String[x]。例如:

package com.hxstrive.jdk8.constructor_ref;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* 构造器引用,用于数组引用
* @author hxstrive.com
*/
public class ConstructorRef04 {

   public static void main(String[] args) {
       List<String[]> strArrayList = Stream.of(10, 20).map(String[]::new).collect(Collectors.toList());
       for(String[] strArray : strArrayList) {
           // 输出数组长度
           System.out.println(strArray.length);
       }
   }

}

运行示例,输出如下:

10
20

数组构造器引用可以用来绕过 Java 中的一个限制。在 Java 中,无法构造一个泛型类型 T 的数组。表达式 new T[n] 是错误的,因为它会被擦除为 new Object[n]。这对于编写 API 的开发人员来说是一个问题。例如,假设我们希望构造一组 String,Stream 接口中有一个返回 Object 数组的 toArray 方法:

Object[] strArray = stream.toArray();

但是这并不能让我们满意。用户希望是一组 String 对象,而不是一组 Object 对象。Stream API 通过构造器引用解决了这个问题。它允许将 String[]::new 传递给 toArray 方法:

String[] strArray = stream.toArray(String[]::new);

toArray 方法会调用该构造器来获得一个正确类型的数组,然后它会填充并返回该数组。例如:

package com.hxstrive.jdk8.constructor_ref;

import java.util.stream.Stream;

/**
* 构造器引用,用于数组引用
* @author hxstrive.com
*/
public class ConstructorRef05 {

   public static void main(String[] args) {
       String[] strArray = Stream.of("Tom", "Helen").toArray(String[]::new);
       for(String str : strArray) {
           System.out.println(str);
       }
   }

}

运行示例,输出如下:

Tom
Helen
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号