java、kotlin反射
反射机制
原理:JVM会持有加载的类的对象 反射就是去 获取指定的class对象 用该对象进行 属性 方法的获取 和 调用
作用:通过反射,可以在运行时获取一个类的所有方法和变量(包括私有)
可以动态地创建对象并调用其属性
破坏封装性?
封装,是将具体的实现细节隐藏,而把功能作为整体提供给类的外部使用,也就是说,公有方法能够完成类所具有的功能。当别人使用这个类时,如果通过反射直接调用私有方法,可能根本实现不了类的功能,甚至可能会出错,因此通过反射调用私有方法可以说是没有任何用处的,开发人员没有必要故意去破坏封装好的类。从这点上看,封装性并没有被破坏。
所谓安全,如果意思是保护实现源码不被别人看见,那没有作用。不用反射也能轻易获取源码。
基本使用:
1 获取class的对象
(1)Class<?> kclass = Class.forName("接口或者类名")
使用Class类的中静态forName()方法获得与字符串对应的Class对象
(2) Class<?> kclass = 类名.class
(3) Class<?> kclass = 对象.getClass()
可以用kclass.toString() 去输出查看 获取的class
2 判断是否为某个类的实例对象
类名.isInstance(对象名)
要反射得到的类 而不是随便的java类名
3 创建实例
(1)
Class<?> c = String.class;
Object str = c.newInstance();
要反射得到的类 而不是随便的java类名
(2)通过constructor方式
//带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
4 获取方法
(1)getDeclaredMethods
获取所有方法(除了继承的的父类的方法)
(2)getMethods
获取所有public方法和其继承的父类的公有方法
(3)getMethod(String name, Class<?>... parameterTypes)
获取指定的public的方法
第一个参数为方法名称,后面的参数为方法的参数对应Class的对象 如int.class
(4)getDeclaredMethod
获取指定的方法 可以private
method.toString()查看获取的具体方法名
静态方法则传null
5 获取类的成员变量(字段)
(1)getDeclaredFields
获取所有成员变量。但不能得到其父类的成员变量
(2)getFileds
访问公有的成员变量
(3)getFiled
获取指定的public属性
(4) getDeclaredField
获取指定的属性可以为private等
返回值为 Field 或者 Field[]
获取值:String xx = field.get(object);
静态属性则传null
设置值:若是private的 加上:
field.setAccessible(true);
6 调用方法
(强转返回类型) 方法.invoke(object obj(获取的类对象),该方法的实参)
若不用创建对象的 直接写null 若通过构造方法或者创建了实例 则传对象
若方法并没有参数 则不用写第二个参数 不是传null
7 创建数组
利用 java.lang.reflect.Array类
Array.newInstance(Class<?> componentType, int length)
第一个参数为class对象 第二个参数为数组长度
注意:由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射。
另外,反射调用方法时可以忽略权限检查
kotlin反射:
要导入包 挺大的 所以尽量还是在java类中用
1 获取kotlin的kclass类的引用:
val c = MyClass::class
2 获取java的类的引用:
val c = MyClass::class.java
Class.forName("xxx.xxx.xxx")
3 获取java类的属性
同java
4 获取kotlin类的属性
val hClass_2=Human::class
val allFields_2=hClass_2.declaredMemberProperties//获取KClass对象的所有属性
val publicFields_2=hClass_2.memberProperties//获取KClass对象的public属性
val extensionFields=hClass_2.declaredMemberExtensionProperties//获取KClass对象的扩展成员变量
val nameField_2=publicFields_2.stream().filter { it.name=="name" }.findAny().get().javaField//获取KClass对象的指定属性,
将KProperty属性类型转换后的类型是java中的Field类型
5 获取java的类的方法
同java
6 获取kotlin类的方法:
//获取KClass对象的所有声明方法,包括父类的方法
val methods_2 = hClass_2.memberFunctions
//获取KClass对象的所有声明方法
val allMethods_2 = hClass_2.declaredMemberFunctions
//返回KClass对象中指定方法名的方法,
将KFunction方法类型转换后的类型是java中的Method类型
val method_2 = methods_2.stream().filter { it.name == "say" }.findAny().get().javaMethod