目录
一、Lambda表达式
特点:
二、函数式接口
1、特点:
2、函数式接口分类
三、方法引用和构造引用
1、方法引用
2、构造引用
四、Stream(流) API
1、定义
2、特点
3、流处理中的持续执行(中间方法)和终止方法
4、如何将数据集转化为Stream
五、接口中的默认方法和静态方法
六、日期时间API
七、OPtional(重要)
1、定义
2、常用方法
八、反射
1、定义
2、反射中所涉及的类
3、获取class的三种方式
一、Lambda表达式
lambda表达式就是匿名函数,匿名函数可以作为参数传递,表示数据。目的是让代码更加简洁,开发更高效!
(参数1,参数2...)->{函数体}
特点:
* 参数的类型可以不写,lambda表达式可以根据上下文进行推断
* 函数体如果只有一行代码,大括号可以不写。
* 如果只有一行代码并且是作为返回值使用,则return也可以不写
* lambda表达式与函数式接口绑定出现
案例1:利用lambda表达式改写Thread线程对象构建
//lambda表达式
Thread thread = new Thread(() -> {
System.out.println("倒数:3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("倒数:2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("倒数:1");
});
thread.start();
案例2:参数根据上下文自动推算
//参数x和y的类型进行了自动推算
MyLambdaTest myLambdaTest = (x, y)->x+y; //()->{return x+y;}
interface MyLambdaTest{
default void printName(){
System.out.println(this.getClass().getName());
}
int sum(int a, int b);
}
二、函数式接口
1、特点:
只包含一个抽象方法的接口就是函数式接口。
如果需要将接口设置为函数式接口,可以在接口上添加注解:
@FunctionalInterface
2、函数式接口分类
jdk内置的函数式接口:
java.util.function:(Function、Consumer、Supplier、Predicate)
函数型接口:有输入参数,也有返回值。Function
案例:
Function<String, Integer> fumc = (x)->x.length();
Integer nihao = fumc.apply("nihao");
System.out.println(nihao);
消费型接口:有参数,没有返回值。Consumer
供给型接口:没有参数,有返回值。Supplier
断言型接口:有输入参数,也有返回值,返回boolean类型。Predicate
补充案例:java支持不定长参数
public static void nums(int ... n){
//System.out.println(n instanceof int[]);
int sum = 0;
for (int num:n) {
sum+=num;
}
System.out.println("所有数值的总和是:"+sum);
}
三、方法引用和构造引用
1、方法引用
当要传递给Lambda体的操作已经有实现方法,可以直接使用方法引用
写法:
对象/类::方法名 //仅仅是引用但不执行
案例:
lambda:
Consumer<String> consumer = (x)-> System.out.println(x);
consumer.accept("hello world");
lambda+函数引用:
Consumer<String> consumer = System.out::println; //此处只是引用out对象的println方法,而不是调用
consumer.accept("hello world");
2、构造引用
//普通构造引用
Supplier<Students> students = Students::new;
students.get().printClassInfo();
class Students{
public void printClassInfo(){
System.out.println(this.getClass().getName());
}
}
//数组构造引用
//可以传递一个参数(表示数组长度),返回数组对象,通过相应类型的构造引用创建对象。
Integer[] arr = new Integer[5];
Function<Integer, Integer[]> integersFunc = (len)->new Integer[len];
//Integer数组的构造引用
Function<Integer, Integer[]> integersFunc1 = Integer[]::new;
Integer[] apply = integersFunc1.apply(6);
System.out.println(Arrays.toString(apply));
四、Stream(流) API
1、定义
jdk1.8提供的一种数据流水线的处理API。
2、特点
* Stream不会存储数据
* Stream在处理完成后会返回一个持有新数据的Stream对象
* Stream中存在持续执行和终止执行的方法(延迟现象)
3、流处理中的持续执行(中间方法)和终止方法
1-中间方法:(流水线的一个操作,不会导致流程结束)
map (mapToInt, flatMap 等)、 filter、 distinct、
sorted、 peek、 limit、 skip、 parallel、
sequential、 unordered
2-终止方法:(调用后,流程结束)
forEach、 forEachOrdered、 toArray、 reduce、
collect、 min、 max、 count、 anyMatch、 allMatch、
noneMatch、 findFirst、 findAny、 iterator
案例1:将流中的数据进行foreach遍历
int[] ints = {12, 25, 66, 71, 45, 99};
IntStream stream = Arrays.stream(ints);
stream.forEach(System.out::println);
案例2:通过中间方法filter过滤数据集中的大于等于60分的值
stream.filter((a)->(a>=60)?true:false).forEach(System.out::println);
4、如何将数据集转化为Stream
1-数组
Arrays工具类中的stream方法
2-集合
集合类身上具有stream方法
3-Stream自带的方法
Stream.of(T ... data)
五、接口中的默认方法和静态方法
默认方法: 被default修饰的方法。
静态方法:直接通过接口名调用,而不需要创建接口的实现类实例。
六、日期时间API
LocalDate; //日期
LocalTime; //时间
LocalDateTime; //日期时间
案例:
//获取当前时间
LocalDateTime now = LocalDateTime.now();
//System.out.println(now.toString());
//日期时间格式化输出
String format = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(format);
//5天之后的日期
LocalDateTime localDateTime = now.plusDays(5);
System.out.println(localDateTime.toString());
//计算两个日期之间相差的天数
//创建未来某个日期的对象: 2023-1-15 10:00:00
LocalDateTime parse = LocalDateTime.parse("2023-01-15T10:00:00");
long until = Math.abs(parse.until(now, ChronoUnit.DAYS));
System.out.println(until);
七、OPtional(重要)
1、定义
OPtional是一个数据容器,可以更好的表达数据是否存在的状态,对空指针可控。
2、常用方法
Optional.of(T t):创建一个Optional实例;
Optional.ofNullable(T t):若t不为空创建一个Optional实例否则创建一个空实例;
Optional.empty():创建一个空的Optional实例;
isPresent():判断是否包含值;
orElse(T t):如果调用对象包含值,返回该值,否则返回t;
orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回s获取的值;
map(Function f):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty();
flatMap(Function mapper):与map类似,要求返回值必须是Optional。
案例:避免空指针问题
String str = null;
//Optional 控制空指针,避免程序运行时由于异常导致终止
Optional<String> str1 = Optional.ofNullable(str);
System.out.println(str1.orElse("").length());
八、反射
1、定义
反射是指动态获取类或者对象的信息(属性和方法),以及动态操作对象的属性和方法的类,动态分析和使用类的信息的类。java为程序员提供的一种可以基于已经存在的对象进行反向探知的能力。
2、反射中所涉及的类
Class //表示一个类
Method //方法
Field //字段,属性
Constructor //构造器
3、获取class的三种方式
要操作一个类的字节码,需要首先获取到这个类的字节码。
-
Class.forName() //Class的静态方法
-
对象.getClass() //通过对象的getClass方法
- 类.class //通过类的class属性
案例1:Class.forName
//字节码
Class<?> uClass = Class.forName("cn.hxzy.apimod.day14.UserControl");
//转化为对应的类型
UserControl userControl = (UserControl) uClass.newInstance();
boolean stat = userControl.registUser("张三", "123456");
System.out.println(stat);
案例2:类.Class
Class<UserControl> userControlClass = UserControl.class;
//new UserControl()
UserControl userControl = userControlClass.newInstance();
案例3:获取所有方法
//获取类中的所有方法
Method[] methods = userControlClass.getMethods(); //包括隐藏父类Object中的方法
Stream<Method> metdStream = Stream.of(methods);
metdStream.forEach(System.out::println);
案例4:获取字段(忽略权限修饰符)
Field[] fields = userControlClass.getDeclaredFields();
Stream<Field> fields1 = Stream.of(fields);
fields1.forEach(System.out::println);
案例5:获取构造器
//获取构造
Constructor<?>[] constructors = userControlClass.getDeclaredConstructors();
Stream<Constructor<?>> constructors1 = Stream.of(constructors);
constructors1.forEach(System.out::println);
案例6:通过构造器创建对象
Class<UserControl> userControlClass = UserControl.class;
//基于带参数的构造器创建对象
Constructor<UserControl> constructor = userControlClass
.getDeclaredConstructor(Integer.class, String.class, String.class, String.class);
constructor.setAccessible(true); //允许访问
UserControl userControl = constructor.newInstance(1, "zhangsan", "123456", "成都");
String address = userControl.getAddress();
System.out.println(address);
案例7:执行方法
//获取字节码
Class<UserControl> userControlClass = UserControl.class;
//获取当前对象
UserControl userControl = userControlClass.newInstance();
//获取方法
Method registUser = userControlClass.getMethod("registUser", String.class, String.class);
//执行方法
Object methodResult = registUser.invoke(userControl, "lisi", "ls123456");
System.out.println(methodResult);
案例8:设置字段
//获取字节码
Class<UserControl> userControlClass = UserControl.class;
//创建对象
UserControl userControl = userControlClass.newInstance();
//获取字段
Field name = userControlClass.getDeclaredField("name");
name.setAccessible(true);
name.set(userControl, "wangwu");
Object nameField = name.get(userControl);
System.out.println(nameField);
案例9:获取类实现的接口
//获取字节码
Class<UserControl> userControlClass = UserControl.class;
//获取当前类实现的接口
Class<?>[] interfaces = userControlClass.getInterfaces();
for (Class<?> interfaceItm:interfaces) {
System.out.println(interfaceItm.getName());
}
案例10:获取注解
//获取字节码
Class<UserControl> userControlClass = UserControl.class;
//获取方法
Method registUser = userControlClass
.getMethod("registUser", String.class, String.class);
//获取当前方法上被修饰的注解,如果当前方法上被@Deprecated修饰,则输出,该方法不可用
Deprecated annotation = registUser.getAnnotation(Deprecated.class);
//System.out.println(annotation.toString());
if(null != annotation) {
System.out.println("方法即将被废弃,不推荐使用!");
}