反射

本文深入探讨了Java反射机制的原理与应用,通过多个实例展示了如何使用反射获取类名、属性、接口、修饰符、构造函数、父类以及方法等关键信息。详细解释了反射在Java开发中的重要作用。

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

说到反射,相信有过编程经验的人都不会陌生。反射机制让Java变得更加的灵活。反射机制在Java的众多特性中是非常重要的一个。下面就让我们一点一点了解它是怎么一回事。


什么是反射

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


反射有什么用

1,在运行时判断任意一个对象所属的类;

2,在运行时构造任意一个类的对象;

3,在运行时判断任意一个类所具有的成员变量和方法;

4,在运行时调用任意一个对象的方法;

5,生成动态代理。


反射的API

学习一门语言,一种比较好的方式就是看它的API文档,因为它的API是最权威的,最准确的。下面我们一起看看JDK的API对于反射是如何描述的吧!


与反射有关的所有接口以及类都在java.lang.reflect包里。


接口

接口摘要

AnnotatedElement
    

表示目前正在此 VM 中运行的程序的一个已注释元素。

GenericArrayType
    

GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。

GenericDeclaration
    

声明类型变量的所有实体的公共接口。

InvocationHandler
    

InvocationHandler 是代理实例的调用处理程序 实现的接口。

Member
    

成员是一种接口,反映有关单个成员(字段或方法)或构造方法的标识信息。

ParameterizedType
    

ParameterizedType 表示参数化类型,如 Collection<String>。

Type
    

Type 是 Java 编程语言中所有类型的公共高级接口。

TypeVariable<D extends GenericDeclaration>
    

TypeVariable 是各种类型变量的公共高级接口。

WildcardType
    

WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。




类摘要

AccessibleObject
    

AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。

Array
    

Array 类提供了动态创建和访问 Java 数组的方法。

Constructor<T>
    

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

Field
    

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

Method
    

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。

Modifier
    

Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。

Proxy
    

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

ReflectPermission
    

反射操作的 Permission 类。


下面给大家写了一个小实例:

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection;  
      
    public class UserInfo {  
          
        private Integer id;  
        private String userName;  
        private String password;  
        public Integer getId() {  
            return id;  
        }  
        public void setId(Integer id) {  
            this.id = id;  
        }  
        public String getUserName() {  
            return userName;  
        }  
        public void setUserName(String userName) {  
            this.userName = userName;  
        }  
        public String getPassword() {  
            return password;  
        }  
        public void setPassword(String password) {  
            this.password = password;  
        }  
          
        @Override  
        public String toString(){  
            return this.getClass().getName();  
        }  
          
    }  



[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection;  
      
    public class GetClass {  
      
        public boolean ClassCheck(){  
            try {  
                  
                System.out.println("第一种,通过类本身获得对象");  
                Class UserClass = this.getClass();  
                System.out.println("第一种方式成功!类名:"+UserClass.toString()+"\n");  
                  
                System.out.println("第二种,通过子类实例获取父类");  
                UserInfo ui = new UserInfo();  
                UserClass = ui.getClass();  
                Class SubUserClass = UserClass.getSuperclass();  
                System.out.println("第二种方式成功!类名:"+SubUserClass.toString()+"\n");  
                  
                System.out.println("第三种,通过类名加.class获得对象");  
                Class ForClass = reflection.UserInfo.class;  
                System.out.println("第三种方式成功!类名:"+ForClass.toString()+"\n");  
                  
                System.out.println("第四种,通过类名的字符串获得对象");  
                Class ForName = Class.forName("reflection.UserInfo");  
                System.out.println("第四种方式成功!类名:"+ForName.toString()+"\n");  
                  
            } catch (Exception e) {  
                e.printStackTrace();  
                return false;  
            }  
            return true;  
        }  
          
        @Override  
        public String toString(){  
            return this.getClass().getName();  
        }  
          
        public static void main(String[] args) {  
            GetClass gc = new GetClass();  
            gc.ClassCheck();  
            if (gc.ClassCheck()) {  
                System.out.println("所有反射全部成功!");  
            }  
            else {  
                System.out.println("反射有问题,请检查!");  
            }  
        }  
      
    }  


向大家介绍了什么是Java的反射机制,以及Java的反射机制有什么用。上一篇比较偏重理论,理论的东西给人讲出来总感觉虚无缥缈,还是结合一些实例比较形象具体。那么今天就结合更多的实例具体说说。


实例一:获得完整的类名

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getclassname;  
      
    //获得完整的类名  
    public class GetClassName {  
      
        public String getNameByClass() {  
              
            String name = "";  
            System.out.println("通过类本身获得对象");  
            Class UserClass = this.getClass();  
            System.out.println("获得对象成功!\n");  
              
            System.out.println("通过类对象获得类名");  
            name = UserClass.getName();  
            System.out.println("获得类名成功!");  
            return name;  
        }  
        public static void main(String[] args) {  
              
            GetClassName gcn = new GetClassName();  
            System.out.println("类名为:"+gcn.getNameByClass());  
        }  
      
    }  


运行结果:

通过类本身获得对象
获得对象成功!

通过类对象获得类名
获得类名成功!
类名为:reflection.getclassname.GetClass Name       


实例二:获得类的属性

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getfields;  
      
    import java.lang.reflect.Field;  
      
    //获得类的属性  
    public class GetFields {  
      
        public static void getFieldNames(String className) {  
              
            try {  
                //获得类名  
                Class c = Class.forName(className);  
                //获得所有属性  
                Field[] fds = c.getFields();  
                  
                for (int i=0; i<fds.length; i++)  
                {  
                    String fn = fds[i].getName();  
                    Class tc = fds[i].getType();  
                    String ft = tc.getName();  
                    System.out.println("该属性的名字为:"+fn+",该属性的类型为:"+ft);  
                }  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) {  
            GetFields.getFieldNames("reflection.getfields.FieldInfo");  
        }  
      
    }  


运行结果:

该属性的名字为:id,该属性的类型为:java.lang.String

该属性的名字为:username,该属性的类型为:java.lang.String    


实例三:获得类实现的接口

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getinterfaces;  
      
    //获得类实现的接口  
    public class GetInterfaces {  
      
        public static void getInterfaces(String className) {  
            try {  
                //取得类  
                Class cl = Class.forName(className);  
                Class[] ifs = cl.getInterfaces();  
                for (int i = 0; i<ifs.length;i++)  
                {  
                    String IName = ifs[i].getName();  
                    System.out.println("该类实现的接口名字为:"+IName);  
                }  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) {  
            GetInterfaces.getInterfaces("reflection.getinterfaces.Student");  
        }  
      
    }  


运行结果:

该类实现的接口名字为:reflection.getinterfaces.Person    


实例四:获得类及其属性的修饰符

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getmodifiers;  
      
    import java.lang.reflect.Field;  
    import java.lang.reflect.Modifier;  
      
    import reflection.UserInfo;  
      
    //获得类及其属性的修饰符  
    public class GetModifiers {  
      
        private String username = "liu shui jing";  
        float f = Float.parseFloat("1.000");  
        public static final int i = 37;  
          
        //获得类的修饰符  
        public static String useModifiers(UserInfo ui) {  
              
            Class uiClass = ui.getClass();  
            int m = uiClass.getModifiers();  
            return Modifier.toString(m);  
              
        }  
          
        //获得本类属性的修饰符  
        public void checkThisClassModifiers() {  
              
            Class tc = this.getClass();       
            Field fl[] = tc.getDeclaredFields();  
          
            for(int i=0;i<fl.length;i++)  
            {  
                System.out.println("第"+(i+1)+"个属性的修饰符为:"+Modifier.toString(fl[i].getModifiers()));  
            }  
              
        }  
        public static void main(String[] args) {  
              
            //获得类的修饰符  
            UserInfo ui =new UserInfo();  
            System.out.println("获得这个类的修饰符:"+GetModifiers.useModifiers(ui)+"\n");  
              
            //获得本类属性的修饰符  
            GetModifiers gm = new GetModifiers();  
            gm.checkThisClassModifiers();  
              
        }  
      
    }  

运行结果:

获得这个类的修饰符:public

 

第1个属性的修饰符为:private

第2个属性的修饰符为:

第3个属性的修饰符为:public static final      



实例五:获得类的构造函数

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getconstructor;  
      
    import java.lang.reflect.Constructor;  
      
    //获得类的构造函数  
    public class GetConstructor {  
      
        //构造函数一  
        GetConstructor(int a) {  
              
        }  
          
        //构造函数二  
        GetConstructor(int a, String b) {  
              
        }  
          
        public static void getConstructorInfo(String className) {  
            try {  
                //获得类的对象  
                Class cl =Class.forName(className);  
                System.out.println("获得类"+className+"所有的构造函数");  
                Constructor ctorlist[] = cl.getDeclaredConstructors();  
                System.out.println("遍历构造函数\n");  
                for(int i =0 ; i<ctorlist.length; i++)  
                {  
                    Constructor con = ctorlist[i];  
                    System.out.println("这个构造函数的名字为:"+con.getName());  
                    System.out.println("通过构造函数获得这个类的名字为:"+con.getDeclaringClass());  
                      
                    Class cp[] = con.getParameterTypes();  
                    for (int j=0; j<cp.length; j++)  
                    {  
                        System.out.println("参数 "+j+" 为 "+cp[j]+"\n");  
                    }  
                }  
            }catch (Exception e) {  
                    System.err.println(e);            
            }  
        }  
        public static void main(String[] args) {  
            GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");  
        }  
      
    }  


运行结果:

获得类reflection.getconstructor.GetConstructor所有的构造函数

遍历构造函数

 

这个构造函数的名字为:reflection.getconstructor.GetConstructor

通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor       

参数 0 为 int

 

这个构造函数的名字为:reflection.getconstructor.GetConstructor

通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor

参数 0 为 int

 

参数 1 为 class java.lang.String


实例六:获得父类

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getparentclass;  
      
    //获得父类  
    public class GetParentClass {  
      
        public static String getParentClass(UserInfoMore uim) {  
              
            //获得父类  
            Class uimc = uim.getClass().getSuperclass();  
            System.out.println("获得父类的名字为:"+uimc.getName());  
            return uimc.getName();  
              
        }  
          
        public static void searchParentClass() {  
              
        }  
          
        public static void main(String[] args) {  
              
            UserInfoMore uim = new UserInfoMore();  
            System.out.println("成功获得UserInfoMore的父类:"+GetParentClass.getParentClass(uim));  
              
        }  
      
    }  


运行结果:

获得父类的名字为:reflection.UserInfo

成功获得UserInfoMore的父类:reflection.UserInfo   


实例七:获得类的方法

[java] view plaincopy在CODE上查看代码片派生到我的代码片

    package reflection.getmethod;  
      
    import java.lang.reflect.Method;  
      
    //获得类的方法  
    public class GetMethod {  
      
        public static void getMethods(String className) {  
            try {  
                System.out.println("开始遍历类"+className+".class");  
                //获得类名  
                Class cls = Class.forName(className);  
                //利用方法获得所有该类的方法  
                System.out.println("利用类的getDeclaredMethods获得类的所有方法");  
                Method ml[] =cls.getDeclaredMethods();  
                System.out.println("遍历获得的方法数组\n");  
                for (int i = 0 ;i<ml.length;i++)  
                {  
                    System.out.println("开始遍历第"+(i+1)+"个方法");  
                    Method m = ml[i];  
                    System.out.println("开始获取方法的变量类型");  
                    Class ptype[] = m.getParameterTypes();  
                    for (int j=0; j<ptype.length; j++)  
                    {  
                        System.out.println("方法参数"+j+"类型为"+ptype[j]);  
                    }  
                    Class gEx[] = m.getExceptionTypes();  
                    for (int j=0 ; j<gEx.length; j++)  
                    {  
                        System.out.println("异常"+j+"为"+ gEx[j]);  
                    }  
                      
                    System.out.println("该方法的返回值类型为:"+m.getReturnType()+"\n");  
                      
                }  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) {  
            GetMethod.getMethods("reflection.UserInfo");  
        }  
      
    }  


运行结果:

开始遍历类reflection.UserInfo.class

利用类的getDeclaredMethods获得类的所有方法         

遍历获得的方法数组

 

开始遍历第1个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.String

 

开始遍历第2个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.Integer

 

开始遍历第3个方法

开始获取方法的变量类型

方法参数0类型为class java.lang.String

该方法的返回值类型为:void

 

开始遍历第4个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.String

 

开始遍历第5个方法

开始获取方法的变量类型

方法参数0类型为class java.lang.Integer

该方法的返回值类型为:void

 

开始遍历第6个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.String

 

开始遍历第7个方法

开始获取方法的变量类型

方法参数0类型为class java.lang.String

该方法的返回值类型为:void

 

转载于:https://my.oschina.net/u/2274056/blog/371629

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值