android 中的反射机制和java的对比
2016-08-14 11:42
381 查看
本文介绍 android 反射和实现原理
反色的概念:
Java反射是可以让我们在运行时获取类的函数、属性、父类、接口等Class
内部信息的机制。通过反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set
方法获取变量的值,即使方法或属性是私有的的也可以通过反射的形式调用,这种“看透class”的能力被称为内省,这种能力在框架开发中尤为重要。有些情况下,我们要使用的类在运行时才会确定,这个时候我们不能在编译期就使用它,因此只能通过反射的形式来使用在运行时才存在的类(该类符合某种特定的规范,例如
JDBC),这是反射用得比较多的场景。
还有一个比较常见的场景就是编译时我们对于类的内部信息不可知,必须得到运行时才能获取类的具体信息。比如 ORM
框架,在运行时才能够获取类中的各个属性,然后通过反射的形式获取其属性名和值,存入数据库。这也是反射比较经典应用场景之一。
Java反射的对比
在Java中的反射机制,被称为Reflection(大家看到这个单词,第一个想法应该就是去开发文档中搜一下了)。它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法。Reflection机制允许程序在正在执行的过程中,利用Reflection APIs取得任何已知名称的类的内部信息,包括:package、 type parameters、 superclass、 implemented interfaces、 inner classes、 outer classes、 fields、 constructors、 methods、 modifiers等,并可以在执行的过程中,动态生成Instances、变更fields内容或唤起methods。
在你想检查一个类的信息之前,你首先需要获取类的 Class
对象。Java
中的所有类型包括基本类型,即使是数组都有与之关联的 Class
类的对象。如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的 Class
对象。
Class<?> myObjectClass = MyObject.class;
如果你已经得到了某个对象,但是你想获取这个对象的 Class
对象,那么你可以通过下面的方法得到:
Studentme = new Student("mr.simple");
Class<?> clazz = me.getClass();
如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class
对象:
Class<?> myObjectClass =Class.forName("com.simple.User");
在使用 Class.forName()方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字。例如 User
类位于 com.simple
包,那么他的完整类路径就是 com.simple.User。
如果在调用 Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出
ClassNotFoundException。
接口说明
//加载指定的 Class
对象,参数 1
为要加载的类的完整路径,例如"com.simple.Student". (
常用方式)
public static Class<?> forName (String className)
//加载指定的 Class
对象,参数 1
为要加载的类的完整路径,例如"com.simple.Student";
//参数 2
为是否要初始化该 Class
对象,参数 3
为指定加载该类的 ClassLoader.
通过上述代码,我们就可以在运行时通过完整的类名来构建对象。
//获取一个公有的构造函数,参数为可变参数,如果构造函数有参数,那么需要将参数的类型传递给 getConstructor
方法
publicConstructor<T> getConstructor (Class...<?>parameterTypes)
//获取目标类所有的公有构造函数
publicConstructor[]<?> getConstructors ()
注意,当你通过反射获取到Constructor、Method、Field
后,在反射调用之前将此对象的 accessible
标志设置为 true,以此来提升反射速度。值为 true
则指示反射的对象在使用时应该取消 Java
语言访问检查。值为 false
则指示反射的对象应该实施 Java
语言访问检查。例如 :
Constructor<?>constructor = clz.getConstructor(String.class);
//设置Constructor
的 Accessible
constructor.setAccessible(true);
//设置 Methohd
的Accessible
Method learnMethod =Student.class.getMethod("learn", String.class);
learnMethod.setAccessible(true);
由于后面还会用到 Student
以及相关的类,我们在这里就先给出它们的代码吧。
Person.java
public class Person {
String mName;
publicPerson(String aName) {
mName = aName;
}
private voidsayHello(String friendName) {
System.out.println(mName + " say hello to " + friendName);
}
protected voidshowMyName() {
System.out.println("My name is " + mName);
}
public voidbreathe() {
System.out.println(" take breathe ");
}
}
Student.java
public class Studentextends Person implements Examination {
//年级
int mGrade;
publicStudent(String aName) {
super(aName);
}
public Student(intgrade, String aName) {
super(aName);
mGrade = grade;
}
private voidlearn(String course) {
System.out.println(mName + " learn " + course);
}
public voidtakeAnExamination() {
System.out.println("takeAnExamination ");
}
public StringtoString() {
return "Student: " + mName;
}
Breathe.java
//呼吸接口
public interface Breathe {
public voidbreathe();
}
Examination.java
//考试接口
public interface Examination {
public voidtakeAnExamination();
}
3反射获取类中函数
3.1获取当前类中定义的方法
要获取当前类中定义的所有方法可以通过 Class
中的 getDeclaredMethods
函数,它会获取到当前类中的 public、default、protected、private
的所有方法。而 getDeclaredMethod(String name,Class...<?> parameterTypes)则是获取某个指定的方法。代码示例如下 :
private static voidshowDeclaredMethods() {
Studentstudent =new Student("mr.simple");
Method[]methods = student.getClass().getDeclaredMethods();
for (Methodmethod : methods) {
System.out.println("declared method name : " +method.getName());
}
try {
MethodlearnMethod = student.getClass().getDeclaredMethod("learn",String.class);
//获取方法的参数类型列表
Class<?>[] paramClasses = learnMethod.getParameterTypes() ;
for(Class<?> class1 : paramClasses) {
System.out.println("learn 方法的参数类型 : " + class1.getName());
}
//是否是 private
函数,属性是否是 private
也可以使用这种方式判断
System.out.println(learnMethod.getName() + " is private "
+Modifier.isPrivate(learnMethod.getModifiers()));
learnMethod.invoke(student, "java ---> ");
} catch(Exception e) {
e.printStackTrace();
}
}
3.2获取当前类、父类中定义的公有方法
要获取当前类以及父类中的所有 public
方法可以通过 Class
中的 getMethods
函数,而 getMethod
则是获取某个指定的方法。代码示例如下 :
private static voidshowMethods() {
Studentstudent= new Student("mr.simple");
//获取所有方法
Method[]methods = student.getClass().getMethods();
for (Methodmethod : methods) {
System.out.println("method name : " + method.getName());
}
try {
//通过getMethod
只能获取公有方法,如果获取私有方法则会抛出异常,比如这里就会抛异常
MethodlearnMethod = student.getClass().getMethod("learn", String.class);
//是否是 private
函数,属性是否是 private
也可以使用这种方式判断
System.out.println(learnMethod.getName() + " is private " +Modifier.isPrivate(learnMethod.getModifiers()));
//调用 learn
函数
learnMethod.invoke(student, "java");
} catch(Exception e) {
e.printStackTrace();
}
}
属性可以通过 Class
中的 getFields
函数,而 getField
则是获取某个指定的属性。代码示例如下 :
接口说明
这里需要注意的是 getDeclaredField
和 getDeclaredFields
包含 private、protected、default、public
的属性,并且通过这两个函数获取到的只是在自身中定义的属性,从父类中集成的属性不能够获取到。而 getField和 getFields
只包含 public
属性,父类中的公有属性也能够获取到。
对象的父类。
对象中实现的接口。
Java 注解 Annotation,定义注解时我们会通过@Target
指定该注解能够作用的类型,看如下示例:
上述注解的@target
表示该注解只能用在函数上,还有 Type、Field、PARAMETER
等类型,可以参考上述给出的参考资料。通过反射 api
我们也能够获取一个 Class
对象获取类型、属性、函数等相关的对象,通过这些对象的getAnnotation
接口获取到对应的注解信息。首先我们需要在目标对象上添加上注解,例如 :
四、获取类的相关信息
1、获取构造方法
Class类提供了四个public方法,用于获取某个类的构造方法。
Constructor getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
Constructor getConstructors() 返回所有具有public属性的构造函数数组
Constructor getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
Constructor getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
反色的概念:
Java反射是可以让我们在运行时获取类的函数、属性、父类、接口等Class
内部信息的机制。通过反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set
方法获取变量的值,即使方法或属性是私有的的也可以通过反射的形式调用,这种“看透class”的能力被称为内省,这种能力在框架开发中尤为重要。有些情况下,我们要使用的类在运行时才会确定,这个时候我们不能在编译期就使用它,因此只能通过反射的形式来使用在运行时才存在的类(该类符合某种特定的规范,例如
JDBC),这是反射用得比较多的场景。
还有一个比较常见的场景就是编译时我们对于类的内部信息不可知,必须得到运行时才能获取类的具体信息。比如 ORM
框架,在运行时才能够获取类中的各个属性,然后通过反射的形式获取其属性名和值,存入数据库。这也是反射比较经典应用场景之一。
Java反射的对比
在Java中的反射机制,被称为Reflection(大家看到这个单词,第一个想法应该就是去开发文档中搜一下了)。它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法。Reflection机制允许程序在正在执行的过程中,利用Reflection APIs取得任何已知名称的类的内部信息,包括:package、 type parameters、 superclass、 implemented interfaces、 inner classes、 outer classes、 fields、 constructors、 methods、 modifiers等,并可以在执行的过程中,动态生成Instances、变更fields内容或唤起methods。
在你想检查一个类的信息之前,你首先需要获取类的 Class
对象。Java
中的所有类型包括基本类型,即使是数组都有与之关联的 Class
类的对象。如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的 Class
对象。
Class<?> myObjectClass = MyObject.class;
如果你已经得到了某个对象,但是你想获取这个对象的 Class
对象,那么你可以通过下面的方法得到:
Studentme = new Student("mr.simple");
Class<?> clazz = me.getClass();
如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class
对象:
Class<?> myObjectClass =Class.forName("com.simple.User");
在使用 Class.forName()方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字。例如 User
类位于 com.simple
包,那么他的完整类路径就是 com.simple.User。
如果在调用 Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出
ClassNotFoundException。
接口说明
//加载指定的 Class
对象,参数 1
为要加载的类的完整路径,例如"com.simple.Student". (
常用方式)
public static Class<?> forName (String className)
//加载指定的 Class
对象,参数 1
为要加载的类的完整路径,例如"com.simple.Student";
//参数 2
为是否要初始化该 Class
对象,参数 3
为指定加载该类的 ClassLoader.
private static void classForName() {
try {
//
获取
Class
对象
Class<?> clz = Class.forName("org.java.advance.reflect.Student");
//
通过
Class
对象获取
Constructor
,
Student
的构造函数有一个字符串参数
//
因此这里需要传递参数的类型
(Student
类见后面的代码
)
Constructor<?> constructor = clz.getConstructor(String.class);
//
通过
Constructor
来创建
Student
对象
Objectobj = constructor.newInstance("mr.simple");
System.out.println(" obj : " + obj.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
通过上述代码,我们就可以在运行时通过完整的类名来构建对象。
//获取一个公有的构造函数,参数为可变参数,如果构造函数有参数,那么需要将参数的类型传递给 getConstructor
方法
publicConstructor<T> getConstructor (Class...<?>parameterTypes)
//获取目标类所有的公有构造函数
publicConstructor[]<?> getConstructors ()
注意,当你通过反射获取到Constructor、Method、Field
后,在反射调用之前将此对象的 accessible
标志设置为 true,以此来提升反射速度。值为 true
则指示反射的对象在使用时应该取消 Java
语言访问检查。值为 false
则指示反射的对象应该实施 Java
语言访问检查。例如 :
Constructor<?>constructor = clz.getConstructor(String.class);
//设置Constructor
的 Accessible
constructor.setAccessible(true);
//设置 Methohd
的Accessible
Method learnMethod =Student.class.getMethod("learn", String.class);
learnMethod.setAccessible(true);
由于后面还会用到 Student
以及相关的类,我们在这里就先给出它们的代码吧。
Person.java
public class Person {
String mName;
publicPerson(String aName) {
mName = aName;
}
private voidsayHello(String friendName) {
System.out.println(mName + " say hello to " + friendName);
}
protected voidshowMyName() {
System.out.println("My name is " + mName);
}
public voidbreathe() {
System.out.println(" take breathe ");
}
}
Student.java
public class Studentextends Person implements Examination {
//年级
int mGrade;
publicStudent(String aName) {
super(aName);
}
public Student(intgrade, String aName) {
super(aName);
mGrade = grade;
}
private voidlearn(String course) {
System.out.println(mName + " learn " + course);
}
public voidtakeAnExamination() {
System.out.println("takeAnExamination ");
}
public StringtoString() {
return "Student: " + mName;
}
Breathe.java
//呼吸接口
public interface Breathe {
public voidbreathe();
}
Examination.java
//考试接口
public interface Examination {
public voidtakeAnExamination();
}
3反射获取类中函数
3.1获取当前类中定义的方法
要获取当前类中定义的所有方法可以通过 Class
中的 getDeclaredMethods
函数,它会获取到当前类中的 public、default、protected、private
的所有方法。而 getDeclaredMethod(String name,Class...<?> parameterTypes)则是获取某个指定的方法。代码示例如下 :
private static voidshowDeclaredMethods() {
Studentstudent =new Student("mr.simple");
Method[]methods = student.getClass().getDeclaredMethods();
for (Methodmethod : methods) {
System.out.println("declared method name : " +method.getName());
}
try {
MethodlearnMethod = student.getClass().getDeclaredMethod("learn",String.class);
//获取方法的参数类型列表
Class<?>[] paramClasses = learnMethod.getParameterTypes() ;
for(Class<?> class1 : paramClasses) {
System.out.println("learn 方法的参数类型 : " + class1.getName());
}
//是否是 private
函数,属性是否是 private
也可以使用这种方式判断
System.out.println(learnMethod.getName() + " is private "
+Modifier.isPrivate(learnMethod.getModifiers()));
learnMethod.invoke(student, "java ---> ");
} catch(Exception e) {
e.printStackTrace();
}
}
3.2获取当前类、父类中定义的公有方法
要获取当前类以及父类中的所有 public
方法可以通过 Class
中的 getMethods
函数,而 getMethod
则是获取某个指定的方法。代码示例如下 :
private static voidshowMethods() {
Studentstudent= new Student("mr.simple");
//获取所有方法
Method[]methods = student.getClass().getMethods();
for (Methodmethod : methods) {
System.out.println("method name : " + method.getName());
}
try {
//通过getMethod
只能获取公有方法,如果获取私有方法则会抛出异常,比如这里就会抛异常
MethodlearnMethod = student.getClass().getMethod("learn", String.class);
//是否是 private
函数,属性是否是 private
也可以使用这种方式判断
System.out.println(learnMethod.getName() + " is private " +Modifier.isPrivate(learnMethod.getModifiers()));
//调用 learn
函数
learnMethod.invoke(student, "java");
} catch(Exception e) {
e.printStackTrace();
}
}
//
获取
Class
对象中指定函数名和参数的函数,参数一为函数名,参数
2
为参数类型列表
public Method getDeclaredMethod (String name, Class...<?> parameterTypes)
//
获取该
Class
对象中的所有函数
(
不包含从父类继承的函数
)
public Method[] getDeclaredMethods ()
//
获取指定的
Class
对象中的
**
公有
**
函数,参数一为函数名,参数
2
为参数类型列表
public Method getMethod (String name, Class...<?> parameterTypes)
//
获取该
Class
对象中的所有
**
公有
**
函数
(
包含从父类和接口类集成下来的函数
)
public Method[] getMethods ()
4.2 获取当前类、父类中定义的公有属性
要获取当前类以及父类中的所有 public属性可以通过 Class
中的 getFields
函数,而 getField
则是获取某个指定的属性。代码示例如下 :
private static void showFields() {
Studentstudent = new Student("mr.simple");
//
获取当前类和父类的所有公有属性
Field[] publicFields = student.getClass().getFields();
for (Field field : publicFields) {
System.out.println("field name : " + field.getName());
}
try {
//
获取当前类和父类的某个公有属性
Field ageField = student.getClass().getField("mAge");
System.out.println(" age is : " + ageField.getInt(student));
} catch (Exception e) {
e.printStackTrace();
}
}
接口说明
//
获取
Class
对象中指定属性名的属性,参数一为属性名
public Method getDeclaredField (String name)
//
获取该
Class
对象中的所有属性
(
不包含从父类继承的属性
)
public Method[] getDeclaredFields ()
//
获取指定的
Class
对象中的
**
公有
**
属性,参数一为属性名
public Method getField (String name)
//
获取该
Class
对象中的所有
**
公有
**
属性
(
包含从父类和接口类集成下来的公有属性
)
public Method[] getFields ()
这里需要注意的是 getDeclaredField
和 getDeclaredFields
包含 private、protected、default、public
的属性,并且通过这两个函数获取到的只是在自身中定义的属性,从父类中集成的属性不能够获取到。而 getField和 getFields
只包含 public
属性,父类中的公有属性也能够获取到。
5 反射获取父类与接口
5.1 获取父类
获取 Class对象的父类。
Studentstudent = new Student("mr.simple");
Class<?> superClass = student.getClass().getSuperclass();
while (superClass !=null) {
System.out.println("Student's super class is : " + superClass.getName());
//
再获取父类的上一层父类,直到最后的
Object
类,
Object
的父类为
null
superClass = superClass.getSuperclass();
}
5.2 获取接口
获取 Class对象中实现的接口。
private static void showInterfaces() {
Studentstudent = new Student("mr.simple");
Class<?>[] interfaceses = student.getClass().getInterfaces();
for (Class<?> class1 : interfaceses) {
System.out.println("Student's interface is : " + class1.getName());
}
}
6 获取注解信息
在框架开发中,注解加反射的组合使用是最为常见形式的。关于注解方面的知识请参考公共技术点之Java 注解 Annotation,定义注解时我们会通过@Target
指定该注解能够作用的类型,看如下示例:
@Target({
ElementType.METHOD, ElementType.FIELD, ElementType.TYPE
})
@Retention(RetentionPolicy.RUNTIME)
static @interface Test {
}
上述注解的@target
表示该注解只能用在函数上,还有 Type、Field、PARAMETER
等类型,可以参考上述给出的参考资料。通过反射 api
我们也能够获取一个 Class
对象获取类型、属性、函数等相关的对象,通过这些对象的getAnnotation
接口获取到对应的注解信息。首先我们需要在目标对象上添加上注解,例如 :
@Test(tag = "Studentclass Test Annoatation")
public class Studentextends Person implements Examination {
//
年级
@Test(tag = "mGrade Test Annotation ")
int mGrade;
//......
}
四、获取类的相关信息
1、获取构造方法
Class类提供了四个public方法,用于获取某个类的构造方法。
Constructor getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
Constructor getConstructors() 返回所有具有public属性的构造函数数组
Constructor getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
Constructor getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
相关文章推荐
- Android(java)学习笔记106-1:类的加载器(反射机制)
- java中的反射机制在Android开发中的用处
- Android(java)学习笔记106-2:反射机制
- iOS运行时编程(Runtime Programming)和Java的反射机制对比
- android使用java的反射机制跳转Activity
- java中的反射机制在android中的应用
- 野人学Android第三弹——利用java的反射机制创建一个数据操作类
- Android面试系列文章2018之Java部分反射机制篇
- Android 插件化开发——Java的反射机制
- iOS运行时编程(Runtime Programming)和Java的反射机制对比
- Android中使用JAVA的反射机制控制数据连接
- Android 在Java代码中设置style属性--使用代码创建ProgressBar对象(反射机制)
- iOS运行时编程(Runtime Programming)和Java的反射机制对比
- [转载]Java中的类反射机制
- Java 的反射机制(2)
- 利用java的反射机制得到界面类的所有可以增加的事件列表
- 补疑(Java的反射机制)
- Java中的类反射机制
- Java中的类反射机制
- java 反射机制