目录
1.2 lambda语法练习 LambdaTest.class
2.2 Supplier:供给型接口,无参有返回值 T为返回值
2.3 Function::函数式接口,有参有返回值 应该是使用最多的
2.4 Predicate: 断言型接口,有参有返回值,返回值是boolean类型
3.1构造器引用 ClassName::new 就是在函数式接口中简化 new Instance();
3.2 方法引用demo object::method 就是在函数式接口中简化 object.mothod();
3.3 数组引用 Type[]::new ..也是满足函数式接口才能使用的 相当于new String[x]
JDK1.8 新特性学习
学之前先网上抄一段什么是函数式编程?因为jdk1.8的lambda 函数式接口 方法引用都是围绕函数式编程来的
首先,什么是函数式编程,引用廖雪峰先生的教程里面的解释就是说:函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
简单的来说就是,函数也是一等公民了,在java里面一等公民有变量,对象,那么函数式编程语言里面函数也可以跟变量,对象一样使用了,也就是说函数既可以作为参数,也可以作为返回值了。
1.Lambda
1.1 lambda表达式的使用前提
lambda的语法是非常简洁的,但是lambda不是可以随便使用的,使用条件为以下2点
1.方法的参数,或者局部变量的类型必须为接口
2.接口中有且仅有一个抽象方法 ,接口上有@FunctionalInterface的肯定满足条件
1.2 lambda和匿名内部类的对比
1.所需类型不一样
(1.1)匿名内部类的类型可以的类,抽象类,接口
(1.2)lambda需要的类型必须是接口
2.抽象方法的数量不一样
(2.1)匿名内部类所需的接口中的抽象方法是可以任意个,匿名内部类全实现即可
(2.2)lambda表达式所需接口中的抽象方法只能有1个
3.实现原理不一样
(3.1)匿名内部类是在编译后生成一个class,(我们编译后,没运行时编译目录就多了一个$calss)
(3.2)lambda是在程序运行时动态生成class(jdk自带javap的反解析工具可查看)
/*UserEntiry userEntiry= getUser(new Supplier<UserEntiry>() {
@Override
public UserEntiry get() {
return null;
}
});*/
//生产UserEntiry , Supplier<T>为函数式接口 直接使用Lambda语法 我们只关注重写Supplier get方法里的逻辑,而new Supplier<UserEntiry>
/**
* 生产UserEntiry , Supplier<T>为函数式接口 直接使用Lambda语法 我们只关注重写Supplier get方法里的逻辑,而
* new Supplier<UserEntiry>()
* @Override
* public UserEntiry get() {
*
* }
* 这种匿名内部类多余的代码都能省略掉 有用的就是{}中的代码
*/
/** 匿名内部类写法我们单独写一个匿名内部类 不指向任何目标也不会报错
* new AInterface() {
* @Override
* public String getName() {
* return "第二种方式 匿名内部类写法,定义一个匿名类 传入构造器";
* }
*
* };
*
* 而lambda 单独这样写是会报错的 因为没有目标,根本无法知道他是哪个匿名内部类的实现
* ()-> {
* return "第三种方式 lambda写法";
* };
* 必须 把它放到方法入参中,蚕食为函数接口
* new LambdaTest(()-> {
* return "第三种方式 lambda写法";
* }).run();
* 或者赋值给一个函数式接口
* AInterface a=()-> {return "第三种方式 lambda写法";
*
*
*/
/**
* Lambda需要类型推断 并且限制挺多 因为出现冲突的话就不知道我要实现哪个方法
* 所以要求AInterface 只有一个方法,如果有2个就会报错, 因为lambda不知道重写哪一个,可以使用@FunctionalInterface对接口限制,被限制后接口只能有一个方法
* 在符合类型推断的场景下可使用 如最经典的 开启线程 实现Runnable接口重写run方法 在传入Thread构造器方式
* new Thread(()-> {})
*/
/***
* 上面的方法之中可以看出,lambda表达式代替匿名内部类的时候,lambda代码块将会实现代替实现抽象类的方法体,lambda表达式的语法主要由三部分构成:
*
* (1)形参列表,如果只有一个参数可以省略括号,当无参数类型时可以使用()来代替。
*
* (2)箭头->
*
* (3)代码块部分{}
*
* Lambda表达式的类型,也被称为“目标类型(target type)”,lambda表达式的目标类型必须是“函数式接口(functional interface)”。
* 函数式接口代表只包含一个抽象方法的接口。函数式接口可以包含多个默认方法,类方法,但只能声明一个抽象方法。
* 如果采用匿名类型内部类来创建函数式接口的实例,则只需要实现一个抽象方法,在这种情况下即可采用lambda表达式来创建对象,
* 该表达式创建出来的对象目标就是这个函数接口。(可以用@FunctionalInterface注解来对函数接口实行限制)
*
* ##表达式的目标类型必须是明确的函数式接口
*
* ##lambda表达式只能为函数式接口创建对象,lambda表达式只能实现一个方法,因此他它只能为只有一个抽象方法的借口(函数式接口)创建对象。
*
*/
AInterface.class
package com.wying.demo.Lambda;
/**
* description:Lambda学习 定义函数接口
* date: 2021/9/15
* author: gaom
* version: 1.0
*
* @FunctionalInterface注解来对函数接口实行限制
* 当有@FunctionalInterface注解时 只能有一个方法 当增加 getName1方法时会报错
*/
@FunctionalInterface
public interface AInterface {
public String getName() ;
// public String getName1() ;
}
1.2 lambda语法练习 LambdaTest.class
package com.wying.demo.Lambda;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* description:Lambda语法学习
* 总结 lambda本质上就是匿名内部类的简化写法,我们在实现匿名内部类时最终的目的就是重写方法里的代码段,其他的都不关心,但是必须都要有,导致代码看起来不简洁
* 在满足lambda语法条件时,使用lambda简化代码,所以lambda并不是什么jdk功能的增强,只能说是简化代码而已。
*
*
*
* date: 2021/9/15
* author: gaom
* version: 1.0
*
*
*/
public class LambdaTest {
public AInterface aInterface;
//无参构造器
public LambdaTest(){
}
public LambdaTest(AInterface aInterface){
System.out.println("重载构造器 接收AInterface对象");
this.aInterface=aInterface;
}
//新建一个类实现AInterface
class BClass implements AInterface{
@Override
public String getName() {
return "第一种方式,新建一个类实现AInterface";
}
}
/**
* 当构造器的参数 public LambdaTest(AInterface aInterface){} 为函数数接口类型时 Lambda表达式使用场景
* 方法的参数list.stream().forEach(Consumer<? super T> action) 为函数数接口类型时 Lambda表达式使用场景
* @param args
*/
public static void main_1(String args[]){
//第一种方式,新建一个类实现AInterface
new LambdaTest(
new LambdaTest().new BClass()
).run();
//第二种方式 匿名内部类
/** 匿名内部类写法我们单独写一个匿名内部类 不指向任何目标也不会报错
* new AInterface() {
* @Override
* public String getName() {
* return "第二种方式 匿名内部类写法,定义一个匿名类 传入构造器";
* }
*
* };
*
* 而lambda 单独这样写是会报错的 因为没有目标,根本无法知道他是哪个匿名内部类的实现
* ()-> {
* return "第三种方式 lambda写法";
* };
* 必须 把它放到方法入参中,蚕食为函数接口
* new LambdaTest(()-> {
* return "第三种方式 lambda写法";
* }).run();
* 或者赋值给一个函数式接口
* AInterface a=()-> {return "第三种方式 lambda写法";
*
*
*/
new LambdaTest(new AInterface() {
@Override
public String getName() {
return "第二种方式 匿名内部类写法,定义一个匿名类 传入构造器";
}
}).run();
//jdk8之前 我们使用匿名内部类实现接口的方式 等同于我们新建一个Class 实现AInterface接口,重写getName方法
//lambda表达式本质上是一段匿名内部类,也可以是一段可以传递的代码
//第三种方式 lambda表达式写法 等同于第二种写法
/**
* Lambda需要类型推断 并且限制挺多 因为出现冲突的话就不知道我要实现哪个方法
* 所以要求AInterface 只有一个方法,如果有2个就会报错, 因为lambda不知道重写哪一个,可以使用@FunctionalInterface对接口限制,被限制后接口只能有一个方法
* 在符合类型推断的场景下可使用 如最经典的 开启线程 实现Runnable接口重写run方法 在传入Thread构造器方式
* new Thread(()-> {})
*/
new LambdaTest(()-> {
return "第三种方式 lambda写法";
}).run();
List<String> list=new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.stream().forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("遍历list:"+s);
}
});
/**
* list.stream().forEach 使用Lambda 因为forEach方法 接收的参数是一个函数式接口
* forEach方法要求传入一个Consumer对象
* void forEach(Consumer<? super T> action);
*
* Consumer类加了FunctionalInterface注解
* @FunctionalInterface
* public interface Consumer<T> {
*/
list.stream().forEach(s -> {
System.out.println("Lambda语法遍历list:"+s);
});
/***
* 上面的方法之中可以看出,lambda表达式代替匿名内部类的时候,lambda代码块将会实现代替实现抽象类的方法体,lambda表达式的语法主要由三部分构成:
*
* (1)形参列表,如果只有一个参数可以省略括号,当无参数类型时可以使用()来代替。
*
* (2)箭头->
*
* (3)代码块部分{}
*
* Lambda表达式的类型,也被称为“目标类型(target type)”,lambda表达式的目标类型必须是“函数式接口(functional interface)”。
* 函数式接口代表只包含一个抽象方法的接口。函数式接口可以包含多个默认方法,类方法,但只能声明一个抽象方法。
* 如果采用匿名类型内部类来创建函数式接口的实例,则只需要实现一个抽象方法,在这种情况下即可采用lambda表达式来创建对象,
* 该表达式创建出来的对象目标就是这个函数接口。(可以用@FunctionalInterface注解来对函数接口实行限制)
*
* ##表达式的目标类型必须是明确的函数式接口
*
* ##lambda表达式只能为函数式接口创建对象,lambda表达式只能实现一个方法,因此他它只能为只有一个抽象方法的借口(函数式接口)创建对象。
*
*/
}
public void run(){
System.out.println("LambdaTest--getName:"+aInterface.getName());
}
/**
* Lambda 用法 代码段
*/
public static void main(String args[]){
AInterface a1=new AInterface(){
@Override
public String getName() {
return "new一个匿名内部类实现AInterface接口,重写getname方法";
}
};
new LambdaTest(a1).run();
//Lambda写法
/**
* Lambda代码段用法要求定义的变量必须是函数接口 (目标类型必须是函数式接口)
* 如Object o= ()-> "Lambda写法 实现AInterface接口,重写getname方法"; 也会报错
* Lambda代码段需要通过变量的类型 如 AInterface a2= 推导出 变量的值是实现AInterface的类
*
* 如果变量是object类型必须通过强转方式来显式的指定目前类型为函数式接口
* Object o= (AInterface) ()-> "Lambda写法 实现AInterface接口,重写getname方法";
*
*/
AInterface a2=()-> "Lambda写法 实现AInterface接口,重写getname方法";
new LambdaTest(a2).run();
}
}
程序运行效果
2.函数式接口
函数式接口的提出是为了给Lambda表达式的使用提供更好的支持。
什么是函数式接口?
简单来说就是只定义了一个抽象方法的接口(Object类的public方法除外),就是函数式接口,并且还提供了注解:@FunctionalInterface
常见的四大函数式接口
2.1 Consumer <T>:消费型接口,有参无返回值
ConsumerDemo.java
package com.wying.demo.FunctionalInterface;
import org.junit.Test;
import java.util.function.Consumer;
/**
* description:函数式接口学习 Consumer <T>:消费型接口,有参无返回值 T为参数
* date: 2021/9/15
* author: gaom
* version: 1.0
*/
public class ConsumerDemo {
@Test
public void test01(){
String str="<id>00001</id><name>张三<name/>";
/* consumerStr(str, new Consumer<String>() {
@Override
public void accept(String s) {
//自定义消费逻辑
try {
//例如把s存入数据库
System.out.println("开始消费:"+s+"");
Thread.sleep(5000);
System.out.println("完成消费:"+s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});*/
//由于 Consumer <T>是函数式接口 上诉匿名表达式可使用Lambda语法
consumerStr(str,(s)->{
//自定义消费逻辑
try {
//例如把s存入数据库
System.out.println("开始消费:" + s + "");
Thread.sleep(5000);
System.out.println("完成消费:" + s);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("消费完毕线程继续执行");
/**
* 说实话,刚看完jdk8的新特性 感觉这有啥用?我什么业务场景用?
* 上面的代码就是把str存入数据库
* 我得到str后直接封装一个方法写代码把str存数据库不就行了 ?
* 这就是jdk1.8的特性 ,使java语言开始支持真正的数式编程 这样写出来代码还传统编程写出来的感觉模块化,低解耦,规范,我们看到Consumer<T>知道业务逻辑是要消费数据类型T,且不需要返回值
* 在实际场景中,我们对数据的处理,写入数据库操作,不需要返回值的都可以尝试使用Consumer<T>
*
*/
}
/**
* 定义一个消费str的函数 适用于 有参无返回值的业务场景
* @param str
* @param consumer
*/
public void consumerStr(String str, Consumer<String> consumer){
consumer.accept(str);
}
}
2.2 Supplier<T>:供给型接口,无参有返回值 T为返回值
SupplierDemo.class
package com.wying.demo.FunctionalInterface;
import com.wying.demo.entity.UserEntiry;
import org.junit.Test;
import java.util.function.Supplier;
/**
* description:函数式接口学习 Supplier<T>:供给型接口,无参有返回值 T为返回值
* date: 2021/9/15
* author: gaom
* version: 1.0
*/
public class SupplierDemo {
@Test
public void test01(){
/*UserEntiry userEntiry= getUser(new Supplier<UserEntiry>() {
@Override
public UserEntiry get() {
return null;
}
});*/
//生产UserEntiry Supplier<T>为函数式接口 直接使用Lambda语法 我们只关注重写Supplier get方法里的逻辑,而new Supplier<UserEntiry>
/**
* 生产UserEntiry Supplier<T>为函数式接口 直接使用Lambda语法 我们只关注重写Supplier get方法里的逻辑,而
* new Supplier<UserEntiry>()
* @Override
* public UserEntiry get() {
*
* }
* 这种匿名内部类多余的代码都能省略掉
*/
UserEntiry userEntiry= getUser(()->{
//实际业务场景 比如从数据库查询用户,放入实体 不过这个函数接口是没入参的 感觉场景还真有点少 有参数的场景多点
UserEntiry userEntiry_1=new UserEntiry().setId(1).setIdCard("362424xxxx").setName("张三").setPhoneNum("18200010002");
return userEntiry_1;
});
System.out.println("生产完毕 userEntiry:"+userEntiry.toString());
}
/**
* 定义一个生产UserEntiry的函数 适用于 无参有返回值的业务场景
* @param userEntirySupplier
* @return
*/
public UserEntiry getUser(Supplier<UserEntiry> userEntirySupplier){
return userEntirySupplier.get();
}
}
2.3 Function<T,R>::函数式接口,有参有返回值 应该是使用最多的
FunctionDemo.java
package com.wying.demo.FunctionalInterface;
import com.wying.demo.entity.UserEntiry;
import org.junit.Test;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* description:函数式接口学习 Function<T,R>::函数式接口,有参有返回值
* 这个函数式接口应该是使用场景最多,最使用的,有入参,有返回值
* date: 2021/9/15
* author: gaom
* version: 1.0
*/
public class FunctionDemo {
@Test
public void test01(){
String s="<id>1</id>";
//根据s 参数 获取UserEntiry Function<T,R>为函数式接口 直接使用Lambda语法
getUser(s,(param)->{
System.out.println("Function<T,R>入参 :"+param);
// 根据param查询 数据库 获取 用户信息
//....
//查询到用户数据赋值
UserEntiry userEntiry_1=new UserEntiry().setId(1).setIdCard("362424xxxx").setName("张三").setPhoneNum("18200010002");
System.out.println("Function<T,R>返回 :"+userEntiry_1.toString());
return userEntiry_1;
});
}
/**
* Function函数式接口,有参有返回值
* @param s 入参
* @param entiryFunction 返回值
* @return 这里使用的业务场景为 通过入参String 执行业务 返回 UserEntiry
*/
public UserEntiry getUser(String s,Function<String,UserEntiry> entiryFunction){
return entiryFunction.apply(s);
}
}
2.4 Predicate<T>: 断言型接口,有参有返回值,返回值是boolean类型
PredicateDemo.class
package com.wying.demo.FunctionalInterface;
import org.junit.Test;
import java.util.function.Predicate;
/**
* description:函数式接口学习 Predicate<T>: 断言型接口,有参有返回值,返回值是boolean类型
* 适用于根据参数,执行业务 返回 true fasle断言的业务场景
* date: 2021/9/15
* author: gaom
* version: 1.0
*/
public class PredicateDemo {
@Test
public void test01(){
//使用场景
//例如通过入参str 查询数据库,是否存在数据
String str="<id>1</id>";
boolean b=checkUser(str,(param)->{
boolean bool_1=false;
//通过param 查询数据库
//如果数据存在 返回true 否则返回false
/*if(){
}*/
return bool_1;
});
System.out.println("根据str:"+ str+" 查询数据数据存在 返回:"+b);
}
/**
*
* @param str 入参
* @param predicate 断言型接口
* @return boolean
*/
public boolean checkUser(String str, Predicate<String> predicate){
return predicate.test(str);
}
}
3.方法引用
通过jdk1.8的自带的函数式接口使用简便的写法创建对象,数组,调用方法
3.1构造器引用 ClassName::new 就是在函数式接口中简化 new Instance();
当我们想通过函数式接口创建一个对象时可以使用
ConstructorInvokeDemo01.java
package com.wying.demo.FunctionInvoke;
import org.junit.Test;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* description:构造器引用 ClassName::new 就是在函数式接口中简化 new Instance();
* 首先前提条件我们要知道 构造器引用的目的 是想用函数式接口创建一个构造器返回 ,我们使用的函数式接口必须是具有返回值的
* jdk1.8自带的有 Supplier<T> 无参有返回值
* Function<T,R> 有参有返回值
* 这里的返回值是指返回构造器创建的对象 入参为构造器的参数
*
* 不要问我new 一个对象 我直接new就完事
* 比如ConstructorInvokeDemo01 c=new ConstructorInvokeDemo01();即可
* 干嘛要通过一个函数式接口创建
* 比如 new一个对象,构造器无传参数
* Supplier<ConstructorInvokeDemo01> supplier2=ConstructorInvokeDemo01::new;
* ConstructorInvokeDemo01 constructorInvokeDemo01_2= supplier2.get();
*
* new一个对象,构造器有参数
* Function<String,ConstructorInvokeDemo01> function3=ConstructorInvokeDemo01::new;
* System.out.println("构造器引用写法 有参构造器 通过apply传入构造器所需参数 返回一个对象");
* ConstructorInvokeDemo01 constructorInvokeDemo01_3=function3.apply("100");
* 哈哈 可能就是通过函数式接口模块化,规范化把
*
*
* date: 2021/10/27
* author: gaom
* version: 1.0
*/
public class ConstructorInvokeDemo01 {
public ConstructorInvokeDemo01(){
System.out.println("无参构建器");
}
public ConstructorInvokeDemo01(String x){
System.out.println("有参构建器 参数:"+x);
}
/**
* 这里没使用junit 测试 因为 junit内部运行时 也是要实例化一个对象调用test01方法
* ConstructorInvokeDemo01有2个构造器时junit不知道选哪个 导致junit报错
* junit要求实例化的对象只能有无参构造器,即使只有一个带参数的也不行,因为junit初始有参构造器不知道传递什么参数
* @param args
*/
public static void main(String args[]){
ConstructorInvokeDemo01 c=new ConstructorInvokeDemo01();
c.test01();
}
public void test01(){
Supplier<ConstructorInvokeDemo01> supplier=new Supplier() {
@Override
public ConstructorInvokeDemo01 get() {
System.out.println("匿名表达式写法 返回一个对象");
return new ConstructorInvokeDemo01();
}
};
ConstructorInvokeDemo01 constructorInvokeDemo01= supplier.get();
//------------------------------------------------------------------------
Supplier<ConstructorInvokeDemo01> supplier1=()->{
System.out.println("lambda表达式写法 返回一个对象");
return new ConstructorInvokeDemo01();
};
ConstructorInvokeDemo01 constructorInvokeDemo01_1= supplier1.get();
//------------------------------------------------------------------------
System.out.println("构造器引用写法 返回一个对象");
Supplier<ConstructorInvokeDemo01> supplier2=ConstructorInvokeDemo01::new;
ConstructorInvokeDemo01 constructorInvokeDemo01_2= supplier2.get();
//------------------------------------------------------------------------
System.out.println("构造器引用写法 有参构造器 <String>为参数,<ConstructorInvokeDemo01>为构造器类型 返回一个对象");
Function<String,ConstructorInvokeDemo01> function3=ConstructorInvokeDemo01::new;
System.out.println("构造器引用写法 有参构造器 通过apply传入构造器所需参数 返回一个对象");
ConstructorInvokeDemo01 constructorInvokeDemo01_3=function3.apply("100");
//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------
}
}
3.2 方法引用demo object::method 就是在函数式接口中简化 object.mothod();
FunctionInvokeDemo01.java
package com.wying.demo.FunctionInvoke;
import org.junit.Test;
import java.util.function.Consumer;
/**
* description:方法引用demo object::method 就是在函数式接口中简化 object.mothod();
* date: 2021/10/27
* author: gaom
* version: 1.0
*/
public class FunctionInvokeDemo01 {
/**
* 总结就是方法引用也是需要先满足函数式接口 且引用的方法入参必须和函数式接口的方法参数个数,类型一致
* 我们也看到了局限性,方法引用适用于{}代码段中只调用一个方法,如果{}需要调用几个方法及不适用
* 比如 下面的 System.out.println(s); 可以使用方法引用,System.out::println;
* public void accept(String s) {
* System.out.println(s);
* }
* 但是 如果{}中需要执行多个方法调用时 不能使用方法引用
* public void accept(String s) {
* System.out.println(s);
* System.out.println(s+"1");
* }
*
*/
@Test
public void test01(){
Consumer<String> consumer=new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("hello 匿名表达式语法 实现Consumer 重写accept方法");
//------------------------------------------------------------------------
Consumer<String> consumer01=(s)->{System.out.println(s);};
consumer01.accept("hello01 lambda表达式语法 实现Consumer 重写accept方法 ");
//------------------------------------------------------------------------
Consumer<String> consumer02=System.out::println;
consumer02.accept("hello02 静态方法直接类名引用 要求println方法的入参和函数式接口的参数类型数量一致 ");
//------------------------------------------------------------------------
//this::save01 相当于实现了Consumer接口后 重写accept中 {}代码块里执行的语句
Consumer<String> consumer03=this::save01;
consumer03.accept("hello03 非静态方法通过对象引用 要求save01方法的入参和函数式接口的参数类型数量一致 ");
//------------------------------------------------------------------------
Consumer<String> consumer04= FunctionInvokeDemo01::save02;
consumer04.accept("hello04 静态方法直接类名引用 要求save02方法的入参和函数式接口的参数类型数量一致");
}
public void save01(String s01){
System.out.println("保存 s01:"+s01);
}
public static void save02(String s02){
System.out.println("保存 s02:"+s02);
}
}
3.3 数组引用 Type[]::new ..也是满足函数式接口才能使用的 相当于new String[x]
ArrayInvoke.java
package com.wying.demo.FunctionInvoke;
import org.junit.Test;
import java.util.function.Function;
/**
* description:数组引用 Type[]::new ..也是满足函数式接口才能使用的 相当于new String[x]
* date: 2021/10/27
* author: gaom
* version: 1.0
*/
public class ArrayInvoke {
@Test
public void test01(){
// 常规创建数组方式
String [] ary=new String[5];
System.out.println("常规创建数组方式 ary.length:"+ary.length);
//------------------------------------------------------------------------
//数组需要用长度 通过入参传入 创建后需要返回 Function函数式接口满足
//函数式接口创建 匿名内部类
Function<Integer,String[]> function1=new Function<Integer, String[]>() {
@Override
public String[] apply(Integer integer) {
return new String[integer];
}
};
String[] ary1=function1.apply(10);
System.out.println("函数式接口创建 匿名内部类 创建数组方式 ary1.length:"+ary1.length);
//------------------------------------------------------------------------
//函数式接口创建 lambda写法
Function<Integer,String[]> function2=(x)->{return new String[x];};
String[] ary2=function2.apply(20);
System.out.println("函数式接口创建 lambda写法 创建数组方式 ary2.length:"+ary2.length);
//------------------------------------------------------------------------
//函数式接口创建 简化后的 数组引用创建方法 Type[]::new
Function<Integer,String[]> function3=String[]::new;
String[] ary3=function3.apply(30);
System.out.println("函数式接口创建 数组引用写法 创建数组方式 ary3.length:"+ary3.length);
}
}