💜 lambda表达式
格式标准
Lambda表达式的省略模式
Lambda表达式和匿名内部类的区别
方法引用
💜 接口中的方法组成
接口中的默认方法
接口中的静态方法
接口中私有方法
函数式接口
函数式接口概述
常用的函数式接口
🍋 Supplier
🍋 Consumer
Stream流中间操作方法
limit()取前几位、skip()跳过前几个
sorted(),比较器
map 与 mapToInt
Stream流终结操作方法
练习:男演员女演员筛选
Stream流的收集操作
💜 反射
反射获取:class类的对象
反射获取:构造方法
反射获取:类的成员变量
💜 lambda表达式
格式标准
格式:
- (形式参数) -> {代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- -> 箭头:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:方法体内容
组成 Lambda表达式的三要素:
使用前提:必须要有接口,接口中仅有一个抽象方法
注意事项:
必须要有接口
必须要有上下文环境
例如:创建一个线程
new Thread (()-> { System.out.println("多线程"); }).start();
练习1
public interface FlyAble { void fly(String s); }
public class LambdaDemo { public static void main(String[] args) { //匿名内部类方式 usefaly(new FlyAble() { @Override public void fly(String s) { System.out.println(s); } }); System.out.println("_________"); //lambda表达式形式 usefaly((String s)->{ System.out.println(s); }); } public static void usefaly(FlyAble fly){ fly.fly("万里晴空"); } }
可以看出lambda表达式实际是在实例化接口对象,并让其作为参数传递
FlyAble f = s{ System.out.println("飞机飞了"); }; usefaly(f);//只输出飞机飞了
Lambda表达式的省略模式
省略的规则
- 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,和 return关键字可以省略。
Lambda表达式和匿名内部类的区别
所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda 表达式:只能是接口
使用限制不同
- 如果接口中有且仅有一个抽象方法,可以使用 Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用 Lambda表达式
实现原理不同
- 匿名内部类:编译之后,产生一个单独的 .class字节码文件
- Lambda 表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
方法引用
https://www.cnblogs.com/wuhenzhidu/p/10727065.html
类名::instMethod
对象方法引用:会使用lambda表达式中的第一个参数去作为对象,引用类的方法
若Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数时,可以使用对象方法引用。
(x, y) -> x.equals(y);
String::equals;
类型
语法
黑马刘意java基础讲解笔记
对应的Lambda表达式
静态方法引用
类名::staticMethod
(args) -> 类名.staticMethod(args)
实例方法引用
inst::instMethod
(args) -> inst.instMethod(args)
对象方法引用
类名::instMethod
(inst,args) -> 类名.instMethod(args)
构造器引用
类名::new
(args) -> new 类名(args)
- 常量
- public static final
- 抽象方法
- public abstract
- 默认方法 (Java 8)
- 静态方法 (Java 8)
- 私有方法 (Java 9)
设想,如果一个接口更新了一些抽象方法,那么将会导致所有实现该接口的类都必须强制性的重写该方法,但是在实际生活中,有些类并不需要这些新添加的方法,他们想自由的重写,该怎么办呢?
- 默认方法不是抽象方法,所以不强制被重写。
- 默认方法也可以被重写,重写的时候去掉 default关键字
- public 可以省略,default不能省略
- 在接口中default方法是可以有方法体的。
div data-theme="default" data-language="java">default void show3() { }
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
div data-theme="default" data-language="java">static void show() { }
Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:
当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性。
div data-theme="default" data-language="java">private void show() { } private static void method() { } // 运行时出错不允许使用private //private: 接口是需要其他类实现的, 如果方法定义成private, 那么其他任何类都不能访问。 这样的方法即要求被实现,又对任何类不可见, 这是无法实现的。
- 默认方法可以调用私有的静态方法和非静态方法
- 静态方法只能调用私有的静态方法
加上注解:@FunctionalInterface
放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败
div data-theme="default" data-language="java">public static void main(String[] args) { ArrayList<String> array=new ArrayList<String>(); array.add("a"); array.add("bb"); array.add("cccccc"); array.add("ddd"); System.out.println("排序前"+array); Collections.sort(array,getComparator()); System.out.println("排序后"+array); } public static Comparator<String> getComparator(){ //返回一个函数式接口 // return new Comparator<String>() { // @Override // public int compare(String s1, String s2) { // return s1.length()-s2.length(); // } // }; // return (String s1,String s2)->{return s1.length()-s2.length();}; return (s1,s2)->s1.length()-s2.length(); }
其实都是只有一个抽象方法的接口,都必须搭配lambda表达式使用。
Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。
T get() 按照某种实现逻辑(由Lambda表达式实现)返回一个数据
div data-theme="default" data-language="java">public static void main(String[] args) { String s = getString(() -> { return "sss";//实例设置好的的返回 }); System.out.println(s); Integer i=getInteger(()->{return 100;});//实例设置好的的返回 System.out.println(i); } private static String getString(Supplier<String> sup){ return sup.get();//返回传进来的 实例的 get方法的 返回值 } private static Integer getInteger(Supplier<Integer> sup){ return sup.get(); }
div data-theme="default" data-language="java">{ public static void main(String[] args) { int[] arr={10,332,2223,435}; int maxvalue = getMax(() -> { int max = arr[0]; for (int i = 0; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } return max;//作为传递的实例的返回 }); System.out.println(maxvalue); } private static int getMax(Supplier<Integer> sup){ return sup.get(); //实际上是把实例的return 返回回去 } }
Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定
void accept(T t)
对给定的参数执行此操作
default Consumer andThen(Consumer after)
返回一个组合的Consumer,依次执行此操作,然后执行after操作
方法名
说明
boolean test(T t)
对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
default Predicate negate()
返回一个逻辑的否定,对应逻辑非
default Predicate and(Predicate other)
返回一个组合判断,对应短路与
default Predicate or(Predicate other)
返回一个组合判断,对应短路或
col>
col>
R apply(T t)
将此函数应用于给定的参数
default Function andThen(Function after)
返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
td data-cell-id="gspA-41">
方法名
td data-cell-id="8Wzy-41">
说明
td data-cell-id="qjqT-41">
void forEach(Consumer action)
td data-cell-id="Lc0r-41">
对此流的每个元素执行 某种 操作
td data-cell-id="JG2p-41">
long count()
td data-cell-id="y9gT-41">
返回此流中的元素个数
R collect(Collector collector)
工具类 Collectors提供了具体的收集方式
方法名
说明
public static Collector toList()
把元素收集到List集合中
public static Collector toSet()
把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper)
把元素收集到Map集合中
//创建List集合对象 List<String> list = new ArrayList<String>(); list.add("林青霞"); list.add("张曼玉"); list.add("王祖贤"); list.add("柳岩"); //需求1:得到名字为3个字的流 Stream<String> liststream=list.stream().filter(s->s.length()==3); //需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历 List<String> names = liststream.collect(Collectors.toList()); for (String name:names){ System.out.println(name); } //定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成 String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"}; //需求5:得到字符串中年龄数据大于28的流 Stream<String> arraystream=Stream.of(strArray).filter(s->Integer.parseInt(s.split(",")[1])>28); //需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值 Map<String,Integer> map= arraystream.collect(Collectors.toMap(s -> s.split(",")[0], s->Integer.parseInt(s.split(",")[1]))); Set<String> keySet = map.keySet(); for (String key:keySet){ Integer value = map.get(key); System.out.println(key+","+value); }
💜 反射
反射获取:class类的对象
反射获取:构造方法
练习2
/* * 通过反射:访问私有构造器生成对象实例 * */ public class fansheDemo01 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取class对象 Class<?> c = Class.forName("fanshe.Student"); // private Student(String name) Constructor<?> con = c.getDeclaredConstructor(String.class); //访问私有方法:暴力反射 con.setAccessible(true); //实例化 Object obj = con.newInstance("林青霞"); System.out.println(obj); }
反射获取:类的成员变量
public class GetFieldDemo { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class<?> c = Class.forName("fanshe.Student"); // Field[] fields = c.getFields(); Field[] fields = c.getDeclaredFields(); for (Field field:fields){ System.out.println(field); } System.out.println("---------------"); //通过获取到的字段赋值 //获取单个成员变量 Field addressField = c.getDeclaredField("address"); addressField.setAccessible(true);//注意顺序 //创建对象 Constructor<?> con = c.getDeclaredConstructor(); con.setAccessible(true);//注意顺序 Object obj = con.newInstance(); //通过field的方法给对象的对应成员变量赋值 addressField.set(obj,"西安"); System.out.println(obj); } }
反射获取:类的成员方法
练习:通过反射跳过泛型检查
/* * 我有一个 ArrayList<Integer>集合,现在我想在这个集合中添加字符串类型的数据,该怎么实现呢? * */ public class ReflectTset01 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //创建集合、 ArrayList<Integer> array = new ArrayList<Integer>(); array.add(10); array.add(20); array.add(30); //通过反射获取类并访问add成员方法,添加任意类型的参数 Class<? extends ArrayList> c = array.getClass(); Method method = c.getMethod("add", Object.class);//这里add的参数变成了Object method.invoke(array, "hello"); method.invoke(array, "world"); method.invoke(array, "Java"); System.out.println(array);//[10, 20, 30, hello, world, Java]
练习2:运行配置文件的指定内容
/* *文件配置信息class.txt如下 * * className=Reflect04.Teacher methodName=teach * */ public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //从配置文件加载数据 Properties prop=new Properties(); FileReader fr=new FileReader("class.txt"); prop.load(fr); fr.close(); String className = prop.getProperty("className"); String methodName = prop.getProperty("methodName"); //通过反射得到类 Class<?> c = Class.forName(className); Constructor<?> con = c.getConstructor(); Object obj = con.newInstance(); Method method = c.getMethod(methodName); method.invoke(obj); } }
模块化
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/19887.html