day39——JDK1.8新特性
一、上节课回顾
1、反射:就是把Java类中各种成分映射成一个一个的Java对象。
应用:在大多数的框架开发中,都是基于配置文件的。
配置了类,类中的方法。。。底层原理都是反射的。
反射是框架设计的灵魂。
例如:
一个类——>Class类的对象
一个属性——>Field类的对象
一个构造——>Constructor类的对象
一个方法——>Method类的对象
利用反射的计数,可以对一个类进行解剖,进一步的执行。
2、反射中常用的类:
Class类:
一个类——>Class类的对象
Field类:
一个属性——>Field类的对象
Constructor类:
一个构造——>Constructor类的对象
Method类:
一个方法——>Method类的对象
3、操作步骤:
step1:获取Class类的对象
方法一:对象.getClass()——>Class类
方法二:类名.class——>Class类
方法三:Class类,提供一个静态方法:forName("包名.类名")——>Class类
step2:获取Field,Constructor,Method类的实例
一种:getXXX(),getXXXs()
二种:getDeclaredXXX(),getDeclaredXXXs()
A:获取Constructor类的实例:
方式一:获取public的构造方法的实例
getConstructor(Class...可变参)--->Constructor,获取某个指定的构造器实例,匹配形参列表的类型
getConstructors()--->Constructor[],获取所有的public的构造器实例,数组
方法二:获取所有访问权限的构造方法的实例
getDeclaredConstructor(Class...可变参)--->Constructor
getDeclaredConstructors()--->Constructor[]
B:获取Field类的实例
方法一:获取public的属性的实例
方法二:获取所有访问权限的属性的实例
getDeclaredField(String)-->Field,根据属性名获取某个Field类的实例
getDeclaredFields()-->Field[],获取一个数组,所有的Field属性
C:获取Method类的实例
方法一:获取public的方法,包括了继承来的方法
getMethod("方法名",Class...可变参)--->Method,获取某个指定的方法实例,
getMethods()--->Method[],包括了所有的public的方法。包括继承来的方法。
方法二:获取所有访问权限的方法,不扩包括继承来的方法,就是本类中
getDeclaredMethod("方法名",Class...可变参)--->Method,
getDeclaredMethods()--->Method[],所有访问权限的方法,但是不包括继承来的方法。
step3:下一步的操作:
setAccessible(boolean flag)
A:Constructor类的实例
实例化对象:
constructor.newInstance(Object...实参列表);
B:Field类的实例
field.set(对象,属性值);
C:Method类的实例
返回值:method.invoke(对象,Object...实参列表);//执行方法的底层方法
无参无返回值
无参有返回值
有参无返回值
有参有返回值
静态的方法
二、本节课内容
2.1、反射
2.2、单例模式
设计模式:23种设计模式。
单例模式:就是一个类只能产生一个对象。
- 饿汉式:随着类的加载而创建。
- 懒汉式:延迟创建对象。第一次调用getInstance(),才创建对象。
2.3、JDK1.8的新特性
2014年推出的1.8版本。
A:函数式接口
接口:定义了一系列的规则。使用抽象方法:只有功能的声明,没有功能的实现。
关键字:interface,
接口中:只能有抽象方法和静态常量。
函数式接口:只有一个抽象方法的接口,就叫函数式接口。
@FunctionInterface
注解(Annotation):1、解释说明,2、限制约束
@Override,方法重写的注解
B:Lambda表达式
以函数式接口为前提,一个匿名函数。可以作为一个方法的参数进行传递。传入一段代码。
- 匿名对象
- 匿名内部类:以实现接口或者继承父类为前提。
- 匿名函数:
lambda表达式,以函数式接口为前提,表示一个匿名函数:自动匹配接口中的唯一的抽象方法。
/*
* 一、Lambda表达式的基本语法
* JDK1.8引入了Lambda表达式,使用新的操作符:"->",该操作符被称为箭头操作符或者Lambda操作符。
* 左侧:对应Lambda表达式的参数列表
* 接口中唯一的抽象方法的形参列表
* 右侧:对应Lambda体,Lambda表达式要实现的内容
* 方法的方法体,也就是方法的实现。
*
* 理解为:Lambda表达式就是对接口的实现:函数式接口(只有一个抽象方法)
* 左侧:接口中的抽象方法的参数列表
* 右侧:就是抽象方法的实现。
*
* Comparable,Comparator,Runnable。。。
*
* 二、Lambda的语法格式
* 1、无参,无返回值
* ()->System.out.println("Hello Lambda。。");
* 如果lambda中的代码,只有一行,{}可以省略不写。
*
* 2、有参,无返回值
* (x)->System.out.println("x-->"+x);
* 如果参数只有一个,()可以省略不写。
* 参数名字随意起,只要合法即可。个数和接口中的抽象方法的参数列表对应。
*
* 3、有参,有返回值
* (x,y,z)->{
* //方法的实现
* return res;
* }
* 注意点:
* A:如果Lambda体有多行,{}不可以省略,如果仅有一行,{}和return都可以省略。
* B:(int x,int y,String z),Lambda的参数列表,数据类型,可以省略不写,也可以写。如果省略不写,JVM编译器自动进行添加,"类型推断"
* List<String> l1 = new ArrayList<>();//集合的类型推断,jdk1.7出现
String[] arr = {"hello","world"};
总结:
左侧:如果参数只有一个,()可以省略不写。习惯上不省略。
参数列表因为“类型推断”,可以不写参数的类型
右侧:方法实现如果只有一行{}可以省略。习惯上会省略。
方法体中只有一行,{}省略了,return也省略。
三:Lambda表达式,需要以函数式接口为前提。
函数是式接口:接口中只有唯一的一个抽象方法。
因为lambda表达式的本质是“匿名函数”。如果接口中有多个方法,Lambda无法匹配。
*/
public static void main(String[] args) {
// 1.使用匿名内部类
A a1 = new A() {
@Override
public void test1() {
System.out.println("匿名内部类的实现。。");
}
};
a1.test1();
//2.使用Lambda表达式
//->左侧是参数列表
//->右侧是Lambda体,就是方法的实现,{},如果只有一行代码,可以省略不写。
A a2 = ()->System.out.println("Hello Lambda。。");
a2.test1();
System.out.println("---------------------");
//3.有一个参数,没有返回值
B b1 = (x)->System.out.println("x-->"+x);//->左侧,是方法的参数列表,参数名随意起。
b1.test2(100);
B b2 = x->System.out.println("x打印:"+x);//->左侧,参数只有一个,()也可以省略,这个习惯上不省。
b2.test2(200);
System.out.println("---------------------");
//4.有参数,有返回值
//public String test3(int num1,int num2,String s);
C c1 = (x,y,z)->{
System.out.println("x-->"+x);
System.out.println("y-->"+y);
System.out.println("z-->"+z);
return x+y+z;
};//如果lambda体中有多行,{}不能再省了
String res1 = c1.test3(1, 2, "haha");
System.out.println(res1);
C c2 = (a,b,c)-> a+b+c;
//如果lambda体只有一行,{}可以省略不写。return关键字也要省略
String res2 = c2.test3(100, 50, "加法");
System.out.println(res2);
C c3 = (int x,int y,String z)->x+y+z;//lambda表达式的参数列表,数据类型可以省略,也可以写。要么都写,要么都省略
String res3 = c3.test3(100, 200, "hehe");
System.out.println(res3);
}