JAVA反射机制深入学习(一)Java反射概念解析
2016-05-27 23:25
645 查看
首先先来看一下JAVA反射的概念:
JAVA反射(Reflection):在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java的反射机制是java被称为动态语言的一个关键性质。
那么反射机制所能实现的功能有:
1. 只要给定类的全名,即可通过反射获取类的所有信息。
2. 反射可以在程序运行时获取任意一个对象所属的类对象。
3. 在运行时可以获取到类中所有属性对象,并对其操作(包括私有属性)。
4. 在运行时可以获取到类中、父类中所有方法,并调用。
目前主流的应用框架如Struts2、Hibernate、Spring、SpringMVC等框架的核心全部是利用Java的反射机制来实现的。
在学习JAVA的反射机制前我们得先了解下JAVA中的几大对象 Class、Constructor、Field、Method
首先先来看下JAVA中的Class对象
Class其实就是类的类型,比如字符串类型就是String,整形类型就是Integer,String和Integer类型就是Class。
Class对象是运行时获取的
Class对象的常用方法介绍:
getName() 获得类中完整名称
getDeclaredFields() 获得类中的所有属性
getDeclaredMethods() 获得类中所有的方法
getConstructors() 获得类构造方法
newInstance() 实例化类对象
注:newInstance()方法为实例化空参数的类对象时使用。
获取Class对象的有三种方法,我们来通过实例来演示下获取Class对象的三种方式:
首先我们先来创建一个简单的bean来作为被获取的class对象的类
获取class对象的第二种方法是将实例化的类对象转型为Object对象,然后通过Object对象的getClass()方法来返回对应类的Class对象。
获取class对象的第三种方法是通过类的class属性返回类的Class对象。
示例代码如下:
在java反射机制中我们就是使用第一种方式来获取对应的class对象,并使用newInstance()方法来得到对应类的类对象,这样便间接的通过代码的方法获取到了对应类的对象。
接下来再来认识一下Constructor对象
Constructor:类的构造函数反射类,通过getConstructor方法可以获得类的所有构造函数反射对象数组。其中最主要的一个方法是newInstance,通过该方法可以创建一个对象类的实例。相当于new关键字
接下来再来认识一下Field对象
Field:用于表示类中、接口中属性对象的类。包名:java.lang.reflect.field利用他可以用来操作类中所有的属性和属性的信息,不论公有还是私有的。
Field类的常用方法介绍:
getName() 获得属性名称
getType() 获得属性类型
get(Object obj) 取得obj对象中这个属性的值
set(Object obj, Object value) 向obj对象中这个属性赋值value
setAccessible(true) 启用/禁用访问控制权限
我们先来介绍下Class对象中获取Field对象常用的两种方法:
Field[] getDeclaredFields() 获取类中所有的属性信息,包括私有属性信息
Field[] getFields() 获取类中所有的公共属性信息
接下来来演示下Field类常用的一些方法:
最后再来看一下Method对象
Method:表示类中、接口中方法对象的类。包名:java.lang.reflect.method 利用他可以操作类中所有的方法,不论公有还是私有。
Method对象的常用方法介绍:
getName() 获得方法名称
getReturnType() 获得方法返回值类型
invoke(Object obj, Object... args) 利用obj对象调用该方法
getParameterTypes() 获得方法所有参数类型,按照顺序返回Class数组
getDeclaredAnnotations() 获取方法的全部注解
我们先来看一下Class类中获取Method对象的几种常用方式:
Method[] getDeclaredMethods() 获取类中定义的所有方法。
Method getMethod(String name, Class<?>... parameterTypes) 获取某个特定的方法,第一个参数为方法名称,第二个参数为方法参数的类对象。当方法具有多个参数时,传入的是Class数组;当参数为0时,传入null。
在这里必须重点介绍invoke(Object obj, Object... args) 方法。
这个方法是Object对象执行方法的反射,由被执行的方法调用(反着调用,也算反射的小特征),传入的第一个参数是调用该方法的Object对象,第二个参数是调用该方法时应传入的参数。当具有多个参数时,传入Object数组;当参数为0时,传入空的Object数组。
接下来演示一下Methd的一些常用方法。
JAVA反射(Reflection):在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java的反射机制是java被称为动态语言的一个关键性质。
那么反射机制所能实现的功能有:
1. 只要给定类的全名,即可通过反射获取类的所有信息。
2. 反射可以在程序运行时获取任意一个对象所属的类对象。
3. 在运行时可以获取到类中所有属性对象,并对其操作(包括私有属性)。
4. 在运行时可以获取到类中、父类中所有方法,并调用。
目前主流的应用框架如Struts2、Hibernate、Spring、SpringMVC等框架的核心全部是利用Java的反射机制来实现的。
在学习JAVA的反射机制前我们得先了解下JAVA中的几大对象 Class、Constructor、Field、Method
首先先来看下JAVA中的Class对象
Class其实就是类的类型,比如字符串类型就是String,整形类型就是Integer,String和Integer类型就是Class。
Class对象是运行时获取的
Class对象的常用方法介绍:
getName() 获得类中完整名称
getDeclaredFields() 获得类中的所有属性
getDeclaredMethods() 获得类中所有的方法
getConstructors() 获得类构造方法
newInstance() 实例化类对象
注:newInstance()方法为实例化空参数的类对象时使用。
获取Class对象的有三种方法,我们来通过实例来演示下获取Class对象的三种方式:
首先我们先来创建一个简单的bean来作为被获取的class对象的类
public class Book { private int id; private String name; private String type; public Book() { } public Book(int id, String name, String type) { this.id = id; this.name = name; this.type = type; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } }获取class对象的第一种方法是利用Class类forName()静态方法传入一个类的全路径来返回相对应的类的Class对象。
book1=Class.forName("cn.lovepi.reflection.bean.Book");
获取class对象的第二种方法是将实例化的类对象转型为Object对象,然后通过Object对象的getClass()方法来返回对应类的Class对象。
Book book=new Book(); Object object=book; book2=object.getClass();
获取class对象的第三种方法是通过类的class属性返回类的Class对象。
book3=Book.class;
示例代码如下:
public class Main {
public static void main(String[] args){
Class book1=null;
Class book2=null;
Class book3=null;
//获取Class对象的第一种方法
try {
book1=Class.forName("cn.lovepi.reflection.bean.Book");
System.out.println("book1==>"+book1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第二种方法
Book book=new Book(); Object object=book; book2=object.getClass();
System.out.println("book2==>"+book2);
//第三种方法
book3=Book.class;
System.out.println("book3==>"+book3);
//接下来使用newInstance方法来创建一个Book对象。
try {
Book book4= (Book) book3.newInstance();
System.out.println("book4==>"+book4);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
在java反射机制中我们就是使用第一种方式来获取对应的class对象,并使用newInstance()方法来得到对应类的类对象,这样便间接的通过代码的方法获取到了对应类的对象。
接下来再来认识一下Constructor对象
Constructor:类的构造函数反射类,通过getConstructor方法可以获得类的所有构造函数反射对象数组。其中最主要的一个方法是newInstance,通过该方法可以创建一个对象类的实例。相当于new关键字
接下来再来认识一下Field对象
Field:用于表示类中、接口中属性对象的类。包名:java.lang.reflect.field利用他可以用来操作类中所有的属性和属性的信息,不论公有还是私有的。
Field类的常用方法介绍:
getName() 获得属性名称
getType() 获得属性类型
get(Object obj) 取得obj对象中这个属性的值
set(Object obj, Object value) 向obj对象中这个属性赋值value
setAccessible(true) 启用/禁用访问控制权限
我们先来介绍下Class对象中获取Field对象常用的两种方法:
Field[] getDeclaredFields() 获取类中所有的属性信息,包括私有属性信息
Field[] getFields() 获取类中所有的公共属性信息
接下来来演示下Field类常用的一些方法:
package cn.lovepi.reflection.test; import cn.lovepi.reflection.bean.Book; import java.lang.reflect.Field; /** * * 演示Field对象常用的方法 */ public class FieldTest { public static void main(String[] args){ //首先创建一个Book对象 Book book=new Book(); //在book对象中封装相应的数据 book.setId(1); book.setName("走在人生边上"); book.setType("散文"); // show(Book.class); show(book); } /** * 使用传递过来的类对象获取对应的属性信息 * @param cl Class对象 */ public static void show(Class cl){ //获取Class对象中声明的所有属性信息,返回值为Field数组 //此方法可以获取到所有的属性信息 Field[] fields=cl.getDeclaredFields(); //此方法只能获取到Class对象中的公有属性信息 Field[] fields1=cl.getFields(); //遍历数组,取出属性信息 for (Field ff:fields ) { System.out.println("属性名称"+ff.getName()+"属性类型"+ff.getType()); } System.out.println("---------------------------------"); for (Field ff:fields1 ) { System.out.println("属性名称"+ff.getName()+"属性类型"+ff.getType()); } } /** * 利用传递过来的实体类对象可以获取到对应的属性名称已经属性值 * @param ob 实体类对象 */ public static void show(Object ob){ //首先获取Class对象 Class cl=ob.getClass(); //获取属性数组 Field[] fields=cl.getDeclaredFields(); for (Field ff:fields ) { //*非常重要,需要设置当前的私有属性可以被外部访问到 ff.setAccessible(true); try { //获取当前实体类对象中的属性名称和对应的属性值 System.out.println("属性名称=="+ff.getName()+"||"+"属性值=="+ff.get(ob)); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }
最后再来看一下Method对象
Method:表示类中、接口中方法对象的类。包名:java.lang.reflect.method 利用他可以操作类中所有的方法,不论公有还是私有。
Method对象的常用方法介绍:
getName() 获得方法名称
getReturnType() 获得方法返回值类型
invoke(Object obj, Object... args) 利用obj对象调用该方法
getParameterTypes() 获得方法所有参数类型,按照顺序返回Class数组
getDeclaredAnnotations() 获取方法的全部注解
我们先来看一下Class类中获取Method对象的几种常用方式:
Method[] getDeclaredMethods() 获取类中定义的所有方法。
Method getMethod(String name, Class<?>... parameterTypes) 获取某个特定的方法,第一个参数为方法名称,第二个参数为方法参数的类对象。当方法具有多个参数时,传入的是Class数组;当参数为0时,传入null。
在这里必须重点介绍invoke(Object obj, Object... args) 方法。
这个方法是Object对象执行方法的反射,由被执行的方法调用(反着调用,也算反射的小特征),传入的第一个参数是调用该方法的Object对象,第二个参数是调用该方法时应传入的参数。当具有多个参数时,传入Object数组;当参数为0时,传入空的Object数组。
接下来演示一下Methd的一些常用方法。
package cn.lovepi.reflection.test; import cn.lovepi.reflection.bean.Book; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * Created by icarus on 2016/5/27. */ public class MethodTest { public static void main(String[] args){ //首先新建一个Book对象 Book book=new Book(); book.setId(2); book.setName("活着"); book.setType("小说"); // show(book); showUse(book); } /** * 根据传递过来的实体类对象来获得带类对象中的方法信息 * @param ob 实体类对象 */ public static void show(Object ob){ //首先获取Class对象 Class cl=ob.getClass(); //获取所有方法 Method[] methods=cl.getDeclaredMethods(); for (Method m:methods ) { System.out.println("方法名称=="+m.getName()); System.out.println("方法返回值类型=="+m.getReturnType()); System.out.println("方法修饰符标号=="+m.getModifiers()); System.out.println("方法修饰符=="+ Modifier.toString(m.getModifiers())); System.out.println("方法的注解信息为"); Annotation[] annotations=m.getDeclaredAnnotations(); for (Annotation a:annotations ) { System.out.print(a.toString()); } System.out.println("方法的参数列表为"); Class[] cl1=m.getParameterTypes(); for (Class cll:cl1 ) { System.out.print(" "+cll.getName()); } } } /** * 使用传递过来的实体类获取其中的方法并调用 * @param object */ public static void showUse(Object object){ //获取Class对象 Class cl=object.getClass(); try { //获取对应方法,传入方法名和方法参数,方法参数为Class数组 Method m1=cl.getMethod("setName",String.class); //执行该方法,第一个参数为执行该对象的对象, // 第二个参数为方法的参数,方法参数为Object数组 m1.invoke(object,"悲惨的世界"); Method m2=cl.getMethod("getName",null); m2.invoke(object,new Object[0]); Method m3=cl.getMethod("test",new Class[]{String.class,int.class}); m3.invoke(object,new Object[]{"哈哈哈",8}); } catch (Exception e) { e.printStackTrace(); } } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树