31、反射:
User类
(1)发生在程序运行期间的动态机制|行为,是java的唯一动态机制-->反射机制。
a.在运行时判断任意一个对象所属的类;
b.在运行时构造任意一个类的对象;
c.在运行时判断任意一个类所具有的成员变量和方法;
d.在运行时调用任意一个对象的方法;
e.生成动态代理;
①反射的源头:
Class
②Class对象在类第一次加载到内存后就已经存在的,唯一的,不变的,每一个类型只有一个,Class对象可以操作这个类的所有内容(属性方法构造器...)。
③如何获取反射的源头:Class对象。
a.类名.class
b.Class.forName(权限定名) 权限定名:包名.类名 -->推荐。
c.对象.getClass()
(3)反射操作构造器
①构造器
②构造器>[] getConstructors() 返回一个包含 构造器对象的数组, 构造器对象反映了此 类对象所表示的类的所有公共构造函数。
③以上都是获取公共的,被public修饰的构造器
a.构造器
b.构造器>[] getDeclaredConstructors() 返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。
④反射创建对象
a.Class-->T newInstance() 默认调用类型的空构造为对象初始化信息 -->不推荐使用
b.不能确定一个类型是否存在空构造,极有可能遇到运行时异常Constructor---> T newInstance(Object... initargs) 创建对象的同时调用当前构造器为对象初始化信息
(4)①反射操作属性
a.字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
b.字段[] getFields() 返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。
c.字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
d.字段[] getDeclaredFields() 返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。
e.void set(Object obj, Object value) 将指定对象参数上此 字段对象表示的字段设置为指定的新值。
f.Object get(Object obj) 返回指定对象上此 字段表示的字段的值。
②反射操作方法
a.方法 getMethod(String name, 类>... parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
b.方法[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。
c.方法 getDeclaredMethod(String name, 类>... parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。
d.方法[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。
e.Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。
(5)反射操作数组
①static Object newInstance(类> componentType, int length) 创建具有指定组件类型和长度的新数组。
②static Object get(Object array, int index) 返回指定数组对象中索引组件的值。
③static void set(Object array, int index, Object value) 将指定数组对象的索引组件的值设置为指定的新值。
反射常用方法
2、注解 : Annotation
(1)标注,java8引入的注解机制
①作用:
a.注释,b.标志|标识,c.使用注解时可以传递参数,可以在程序中通过反射操作注解,获取配置的信息在程序中使用,d.可以存在于Class文件中,e.大量的代替|简化配置文件的使用
②使用:@注解名(参数)
③注解的分类:
a.jdk的内置注解 : 常见
b.@Override 检查重写方法
c.@SuppressWarnings("all") 抑制警告
d.@Deprecated 表示已过时,不推荐使用
e.@FunctionalInterface 标识函数式接口
④参数的个数分类:a.标志|标识注解b.单值注解c.完整注解d.元注解 : 注解注解的注解e.自定义注解。
(2)元注解 : 就是负责注解其他注解
①@Target 用于描述注解的使用范围
②@Retention 规定注解类型的声明周期
③@Documented 保留在API文档中
④@Inherited 标识注解类型可以被继承
(3)自定义注解
①@interface 定义注解类型
②默认实现java.lang.annotation.Annotation接口
③自定义的注解类型就不能显示的继承其他父类,实现其他接口
④如果注解类中的属性只有一个,建议名字为value,为value属性赋值可以直接赋值
⑤为注解类型定义属性|字段: 数据类型 数据名();
⑥属性的数据类型要求为: 基本数据类型 String, 枚举 , 注解类型 , 以及以上类型的数组
⑦属性可以通过default提供默认值
(4)注解解析器 : 通过反射操作注解
①案例: 自定义水果清单 FruitList,int apple;int pair;为每种水果提供一个默认的进货数量,通过注解进行配置,注解类型: FruitNum 属性: int value();
②注意:如果通过反射操作注解,注解类型的生命周期应该定义为运行期
3、Lambda表达式
注解解析器 : 通过反射操作注解员工类(Emplyee)
(1)题一:调用Collections.sort()方法,通过定值排序比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda作为参数传递
分析:
①定制排序:指自定义比较器|定制排序,自然排序:内部比较器|自然排序
②先比较年龄,年龄相同才比较姓名
(2)习题二:
①声明函数式接口,接口中声明抽象方法,public String getValue(String str)
②声明类 TestLambda,类中编写方法使用接口作为参数,讲一个字符串转成大写,并作为方法的返回值
③再将一个字符串的第2个和第4个索引位置进行截取子串
lambda : 就是把行为作为参数传递,函数式接口作为形参,lambda表达式作为实参,传递行为
(3)习题三:
①声明一个带两个泛型的函数式接口,发型类型为
②接口中声明对应抽象方法
③在TestLambda类中声明方法,参数三个,两个long类型的参数,接口作为参数,接口实现中计算两个long型参数的和
④再计算两个long型参数的乘积
(4)函数式接口
①接口中只与一个必须被重写的抽象方法,@FunctionalInterface
②四大内置函数式接口:
a.消费型接口 Consumer
void accept(T t) --> 有来无回,有参数没有返回值
b.供给型接口 Supplier
T get()
c.函数型接口 Function
R apply(T t)
d.段言型接口 Predicate
boolean test(T t)