java反射思维与NDK开发
Java访问JNI函数与调用其他Java函数没有区别(为什么这么说?原理是啥?之后找)
java反射:
- java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
- 对于任意类的静态属性和方法,都能够完成对静态属性的获取和设置以及静态方法的调用
- 对于任意一个对象,都能够调用它的任意方法和属性
- 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
java反射一般用在什么地方
在日常的第三方应用开发过程中,经常会遇到某个类的成员变量、方法或是属性是私有的或是只对系统应用开发,这时候就可以利用java的反射机制通过反射来获取所需的私有成员或是方法。而对与public类型的成员变量和方法和属性都可以使用反射来进行访问
java反射的相关类
类名 | 用于 |
---|---|
Class类 | 代表类的实体,在运行的java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
获取类相关的方法
方法 | 用途 |
---|---|
asSubClass(Class clazz) | 把传递的类的对象转换成代表其棋类的对象 |
Cast | 把对象转换成代表类或是接口的对象 |
gfetClassLoader() | 获取类的加载器 |
getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
getName() | 获得类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获得类的包 |
getSimpleName() | 获得类的名字 |
getSuperClass() | 获得当前类继承的父类的名字 |
getInterfaces() | 获得当前类实现的类或是接口 |
获取类中属性相关的方法
方法 | 用途 |
---|---|
getField(String name) | 获得某个公有的属性对象 |
getFields() | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
获取类中构造器相关的方法
方法 | 用途 |
---|---|
getConstructor(Class…<?> parameterTypes) | 获得该类中雨参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所以公有构造防范 |
getDeclaredConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
获得类中方法相关的方法
方法 | 用途 |
---|---|
getMethod(String name,Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name,Class…<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
类中其他重要的方法
方法 | 用途 |
---|---|
isAnnotation() | 如果是注解类型则返回true |
isAnnotationPresent(Class<? extends Annotation> annotationClass) | 如果是指定类型注解类型测返回true |
isAnonymousClass() | 如果是匿名类则返回true |
isArray() | 如果是一个数组类则返回true |
isEnum() | 如果是枚举类则返回true |
isInstance(Object obj) | 如果obj是该类的实例则返回true |
isInterface() | 如果是接口类则返回true |
isLocalClass() | 如果是局部类则返回true |
isMemberClass() | 如果是内部类则返回true |
Field类
Field类代表类的成员变量(成员变量也称为类的属性)存在调用静态和非静态的区别
方法 | 用途 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Ojbect obj,Object value) | 设置obj中对应属性值 |
Method类
Method带包类的方法存在调用静态和非静态的区别
方法 | 用途 |
---|---|
invoke(Object obj, Object… args) | 传递object对象及参数调用该对象对应的方法 |
Constructor类
Constructor代表类的构造方法
方法 | 用途 |
---|---|
newInstance(Object… initargs) | 根据传递的参数创建类的对象 |
破坏本身的封装性和安全性,访问private域和方法:
类AccessiableObject中有函数public void setAccessible(boolean flag),该函数在传入true作为参数后,让访问private修饰的域和函数成为可能。而Method、Field和Constructor类共同继承了AccessibleObject类,该基类有两个setAccessible方法能够在运行时压制Java语言访问控制检查(Java language access control checks),从而能任意调用私有化保护的方法、域和构造方法
获取某个类的Class的几种方式
Class testClazz = MainActivity.class.getClassLoader().loadClass("com.showme.reflectiontest.Test");
Class testClazz2 = Class.forName("com.showme.reflectiontest.Test");
// 调用方和被调用方在一个classloader中
Class testClazz3 = Test.class;
属性
getDeclaredField 获取单个的属性 :公有的,私有的
Field publicStaticField_field = testClass.getDeclaredField("publicStaticField");
Field publicNonStaticField = testClass.getDeclaredField("publicNonStaticField");
Field privateStaticField = testClass.getDeclaredField("privateStaticField");
Field privateNonStaticField = testClass.getDeclaredField("privateNonStaticField");
getField 获取单个的属性 :只能获取公有的,私有属性通过设置setAccessible也无法访问
Field publicStaticField_field_getField = testClass.getField("publicStaticField");
Field publicNonStaticField_getField = testClass.getField("publicNonStaticField");
getDeclaredFields 可以获取所有的属性,包含私有的,私有的
Field[] fields = testClass.getDeclaredFields();
for(Field field : fields){
Log.d("showme","getDeclaredFields-> : " + field);
}
getFields 只能获取共有的属性
Field[] getFields = testClass.getFields();
for(Field field : getFields){
Log.d("showme","getFields-> : " + field);
}
获取并修改属性的值
// 获取public静态属性的值
Object publicStaticFieldObject = publicStaticField_field.get(null);
Log.d("showme","publicStaticFieldObject = " + publicStaticFieldObject.toString());
// 获取public非静态属性的值
Object publicNonStaticFieldObject = publicNonStaticField.get(a_obj);
Log.d("showme","publicNonStaticFieldObject = " + publicNonStaticFieldObject.toString());
// 获取private静态属性的值 : 需要设置 setAccessible 为true
privateStaticField.setAccessible(true);
String reuslt = (String) privateStaticField.get(null);
Log.d("showme","privateStaticFieldObject = " + reuslt);
// 获取private非静态属性的值 : 需要设置 setAccessible 为true
privateNonStaticField.setAccessible(true);
privateNonStaticField.set(a_obj,"modified private non static field");
reuslt = (String) privateNonStaticField.get(a_obj);
Log.d("showme","privateNonStaticField = " + reuslt);
方法
getDeclaredMethods 只获取当前类的所有方法,无法获取到基类的方法
Method[] getDeclaredMethods = testExtendClass.getDeclaredMethods();
for(Method method : getDeclaredMethods){
Log.d("showme","getDeclaredMethods -> : " + method);
}
getMethods 无法获取当前类的私有方法,但是可以获取基类类中的公有函数
Method[] getMethods = testExtendClass.getMethods();
for(Method method : getMethods){
Log.d("showme","getMethods-> : " + method);
}
获取方法
// 静态公有方法
Class testClazz = Test.class;
Method publicStaticFunc_method = testClazz.getDeclaredMethod("publicStaticFunc");
publicStaticFunc_method.invoke(null);
// 静态私有方法
Method privateStaticFunc_method = testClazz.getDeclaredMethod("privateStaticFunc");
privateStaticFunc_method.setAccessible(true);
privateStaticFunc_method.invoke(null);
// 非静态方法
Test a_obj = new Test();
Method privateFunc_method = testClazz.getDeclaredMethod("privateFunc");
privateFunc_method.setAccessible(true);
privateFunc_method.invoke(a_obj, ...参数);
获取构造方法
// 获取所有的构造方法
Constructor[] constructors = testClazz.getDeclaredConstructors();
// 获取特定的构造方法
// public Test(String arg, int arg2);
Constructor constructor = testClazz.getDeclaredConstructor(String.class, int.class);
// 无法获取私有的构造函数
Constructor[] constructors1 = testExtendClass.getConstructors();
Constructor constructor = testExtendClass.getConstructor(String.class);
// 反射创建对象
Object testobj = constructor.newInstance("test", 666);
Field privateField_field = testClazz.getDeclaredField("privateField");
privateField_field.setAccessible(true);
String privateField_String = (String) privateField_field.get(testobj);