JAVA反射机制深入学习(一)Java反射概念解析

本文深入讲解Java反射机制的核心概念及应用场景,包括Class、Constructor、Field和Method对象的使用方法,并通过示例代码演示如何获取和操作类的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先先来看一下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对象的类
[java] view plain copy
  1. public class Book {  
  2.     private int id;  
  3.     private String name;  
  4.     private String type;  
  5.   
  6.     public Book() {  
  7.     }  
  8.   
  9.     public Book(int id, String name, String type) {  
  10.         this.id = id;  
  11.         this.name = name;  
  12.         this.type = type;  
  13.     }  
  14.   
  15.     public int getId() {  
  16.         return id;  
  17.     }  
  18.   
  19.     public void setId(int id) {  
  20.         this.id = id;  
  21.     }  
  22.   
  23.     public String getName() {  
  24.         return name;  
  25.     }  
  26.   
  27.     public void setName(String name) {  
  28.         this.name = name;  
  29.     }  
  30.   
  31.     public String getType() {  
  32.         return type;  
  33.     }  
  34.   
  35.     public void setType(String type) {  
  36.         this.type = type;  
  37.     }  
  38.   
  39. }  
获取class对象的第一种方法是利用Class类forName()静态方法传入一个类的全路径来返回相对应的类的Class对象。
[java] view plain copy
  1. book1=Class.forName("cn.lovepi.reflection.bean.Book");  
获取class对象的第二种方法是将实例化的类对象转型为Object对象,然后通过Object对象的getClass()方法来返回对应类的Class对象。
[java] view plain copy
  1. Book book=new Book();  
  2. Object object=book;  
  3. book2=object.getClass();  
获取class对象的第三种方法是通过类的class属性返回类的Class对象。
[java] view plain copy
  1. book3=Book.class;  
示例代码如下:
[java] view plain copy
  1. public class Main {  
  2.     public static void main(String[] args){  
  3.         Class book1=null;  
  4.         Class book2=null;  
  5.         Class book3=null;  
  6.         //获取Class对象的第一种方法  
  7.         try {  
  8.             book1=Class.forName("cn.lovepi.reflection.bean.Book");  
  9.             System.out.println("book1==>"+book1);  
  10.         } catch (ClassNotFoundException e) {  
  11.             e.printStackTrace();  
  12.         }  
  13.         //第二种方法  
  14.         Book book=new Book();  
  15.         Object object=book;  
  16.         book2=object.getClass();  
  17.         System.out.println("book2==>"+book2);  
  18.         //第三种方法  
  19.         book3=Book.class;  
  20.         System.out.println("book3==>"+book3);  
  21.         //接下来使用newInstance方法来创建一个Book对象。  
  22.         try {  
  23.             Book book4= (Book) book3.newInstance();  
  24.             System.out.println("book4==>"+book4);  
  25.         } catch (InstantiationException e) {  
  26.             e.printStackTrace();  
  27.         } catch (IllegalAccessException e) {  
  28.             e.printStackTrace();  
  29.         }  
  30.     }  
  31. }  
在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类常用的一些方法:
[java] view plain copy
  1. package cn.lovepi.reflection.test;  
  2.   
  3. import cn.lovepi.reflection.bean.Book;  
  4.   
  5. import java.lang.reflect.Field;  
  6.   
  7. /** 
  8.  
  9. * 演示Field对象常用的方法 
  10. */  
  11. public class FieldTest {  
  12.     public static void main(String[] args){  
  13.         //首先创建一个Book对象  
  14.         Book book=new Book();  
  15.         //在book对象中封装相应的数据  
  16.         book.setId(1);  
  17.         book.setName("走在人生边上");  
  18.         book.setType("散文");  
  19.   
  20. //        show(Book.class);  
  21.         show(book);  
  22.     }  
  23.   
  24.     /** 
  25.     * 使用传递过来的类对象获取对应的属性信息 
  26.     * @param cl Class对象 
  27.     */  
  28.     public static void show(Class cl){  
  29.         //获取Class对象中声明的所有属性信息,返回值为Field数组  
  30.         //此方法可以获取到所有的属性信息  
  31.         Field[] fields=cl.getDeclaredFields();  
  32.         //此方法只能获取到Class对象中的公有属性信息  
  33.         Field[] fields1=cl.getFields();  
  34.         //遍历数组,取出属性信息  
  35.         for (Field ff:fields  
  36.             ) {  
  37.             System.out.println("属性名称"+ff.getName()+"属性类型"+ff.getType());  
  38.         }  
  39.         System.out.println("---------------------------------");  
  40.         for (Field ff:fields1  
  41.             ) {  
  42.             System.out.println("属性名称"+ff.getName()+"属性类型"+ff.getType());  
  43.         }  
  44.     }  
  45.   
  46.     /** 
  47.     * 利用传递过来的实体类对象可以获取到对应的属性名称已经属性值 
  48.     * @param ob 实体类对象 
  49.     */  
  50.     public static void show(Object ob){  
  51.         //首先获取Class对象  
  52.         Class cl=ob.getClass();  
  53.         //获取属性数组  
  54.         Field[] fields=cl.getDeclaredFields();  
  55.         for (Field ff:fields  
  56.             ) {  
  57.             //*非常重要,需要设置当前的私有属性可以被外部访问到  
  58.             ff.setAccessible(true);  
  59.             try {  
  60.   
  61.                 //获取当前实体类对象中的属性名称和对应的属性值  
  62.                 System.out.println("属性名称=="+ff.getName()+"||"+"属性值=="+ff.get(ob));  
  63.             } catch (IllegalAccessException e) {  
  64.                 e.printStackTrace();  
  65.             }  
  66.         }  
  67.     }  
  68. }  

最后再来看一下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] view plain copy
  1. package cn.lovepi.reflection.test;  
  2.   
  3. import cn.lovepi.reflection.bean.Book;  
  4.   
  5. import java.lang.annotation.Annotation;  
  6. import java.lang.reflect.Method;  
  7. import java.lang.reflect.Modifier;  
  8.   
  9. /** 
  10. * Created by icarus on 2016/5/27. 
  11. */  
  12. public class MethodTest {  
  13.     public static void main(String[] args){  
  14.         //首先新建一个Book对象  
  15.         Book book=new Book();  
  16.         book.setId(2);  
  17.         book.setName("活着");  
  18.         book.setType("小说");  
  19. //        show(book);  
  20.         showUse(book);  
  21.     }  
  22.   
  23.     /** 
  24.     * 根据传递过来的实体类对象来获得带类对象中的方法信息 
  25.     * @param ob 实体类对象 
  26.     */  
  27.     public static void show(Object ob){  
  28.         //首先获取Class对象  
  29.         Class cl=ob.getClass();  
  30.         //获取所有方法  
  31.         Method[] methods=cl.getDeclaredMethods();  
  32.         for (Method m:methods  
  33.             ) {  
  34.             System.out.println("方法名称=="+m.getName());  
  35.             System.out.println("方法返回值类型=="+m.getReturnType());  
  36.             System.out.println("方法修饰符标号=="+m.getModifiers());  
  37.             System.out.println("方法修饰符=="+ Modifier.toString(m.getModifiers()));  
  38.             System.out.println("方法的注解信息为");  
  39.             Annotation[] annotations=m.getDeclaredAnnotations();  
  40.             for (Annotation a:annotations  
  41.                 ) {  
  42.                 System.out.print(a.toString());  
  43.             }  
  44.             System.out.println("方法的参数列表为");  
  45.             Class[] cl1=m.getParameterTypes();  
  46.             for (Class cll:cl1  
  47.                 ) {  
  48.                 System.out.print(" "+cll.getName());  
  49.             }  
  50.         }  
  51.     }  
  52.   
  53.     /** 
  54.     * 使用传递过来的实体类获取其中的方法并调用 
  55.     * @param object 
  56.     */  
  57.     public static void showUse(Object object){  
  58.         //获取Class对象  
  59.         Class cl=object.getClass();  
  60.         try {  
  61.             //获取对应方法,传入方法名和方法参数,方法参数为Class数组  
  62.             Method m1=cl.getMethod("setName",String.class);  
  63.             //执行该方法,第一个参数为执行该对象的对象,  
  64.             // 第二个参数为方法的参数,方法参数为Object数组  
  65.             m1.invoke(object,"悲惨的世界");  
  66.   
  67.             Method m2=cl.getMethod("getName",null);  
  68.             m2.invoke(object,new Object[0]);  
  69.   
  70.             Method m3=cl.getMethod("test",new Class[]{String.class,int.class});  
  71.             m3.invoke(object,new Object[]{"哈哈哈",8});  
  72.         } catch (Exception e) {  
  73.             e.printStackTrace();  
  74.         }  
  75.     }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值