Java中用反射获取类的属性,方法和构造函数

时间:2021-08-19作者:klpeng分类:IT综合浏览:286评论:0

        通过反射机制可以获取一个类的属性,构造函数,方法。

        下面以创建的Person类为例。

        

package com.java.classtest;

public class Person {

    public String name;
    private int age;

    public Person() {

                System.out.println("这是无参构造函数");

    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}
 

        通过Person类的包路径,获取Class对象。

Class c = Class.forName("com.java.classtest.Person");


目录

一、 对Class对象的操作     

二、获取Class对象的属性

三、获取Class对象的方法

四、获取Class对象的构造方法


一、 对Class对象的操作     

        //获取该类的权限修饰符
        String modifiers = Modifier.toString(c.getModifiers());
        System.out.println(modifiers);
        
        //获取该Class对象的全路径
        String name = c.getName();
        System.out.println(name);
        
        //获取该Class对象的简写名字
        String simpleName = c.getSimpleName();
        System.out.println(simpleName);

        //获取父类的名字
        while(c!=null) {
            System.out.println(c.getName());
            c = c.getSuperclass();
        }

        使用的都是Class对象的方法,显而易见的是,对于获取某个东西的值的方法大多是get+获取某事物的英文名(首字母大写)。比如说getPackage() ,返回该类包名。

        其中为了方便,权限修饰符是可以有多个的,如public static final  。 获取权限修饰符getModifiers()是返回一个int型的数字,需要通过Modifier类的toString解析。

        getSuperclass(),就是获取该Class对象的父类Class对象。 

        运行结果为:

Java中用反射获取类的属性,方法和构造函数

         也可以对其Class对象的类型进行判断。判断一个Class对象是一个接口?是一个枚举?是一个数组? 返回一个boolean值,如果判断的符合就会返回true,否则返回false.

        格式为:   is+需要判断类型的英语单词(首字母大写)。

        如isAnnotation(),判断该Class对象是否是一个注解。Annotation的意思是注解。isInterface() 显然就是判断该Class对象是否是接口类型。

        例如:

        System.out.println("该Class对象是否是注解:"+c.isAnnotation());
        System.out.println("该Class对象是否有@Deprecated注解:"+c.isAnnotationPresent(Deprecated.class));
        System.out.println("该Class对象是否是一个接口:"+c.isInterface());
        System.out.println("该Class对象是否是一个枚举:"+c.isEnum());
        System.out.println("该Class对象是否是一个数组:"+c.isArray());

       

        显然,Person所对于的Class对象都不符合上述的条件。

Java中用反射获取类的属性,方法和构造函数

        也可以通过该Class对象new一个无参对象。

        Object obj = c.newInstance();

        当我们执行这条语句时,就会new一个该类的无参构造函数的对象:

        Java中用反射获取类的属性,方法和构造函数

二、获取Class对象的属性

        属性就是变量那些,按照对应上述的规律,其对应方法就是获取字段getField()。不过也有区别。返回的都是Field类对象。

        getField(String name);  //获取名为name的公共字段对象

        getFields();  //获取Class对象所有可访问的公共字段对象数组

        上述的都是必须要字段的权限修饰符为public才能访问。

        Field[] fields = c.getFields();
        System.out.println("Class对象public的属性数为:"+fields.length);

        Field nameField = c.getField("name");
        System.out.println(nameField.getName());
        
        Field ageField = c.getField("age");  //报错找不到
        System.out.println(ageField.getName());

        运行结果:

Java中用反射获取类的属性,方法和构造函数

         如果想要获取字段不受权限修饰符干扰,也是有方法的,按照上述的两个方法 在get  和 Field(String name)/Fields()   之间加上Declared 就可以了。

        按照上述改进:

        Field[] fields = c.getFields();
        System.out.println("Class对象属性数为:"+fields.length);
        for(Field field : fields) {
            System.out.println(field.getName());
        }
            
        System.out.println("------");    
            
        Field nameField = c.getDeclaredField("name");
        System.out.println(nameField.getName());
        
        Field ageField = c.getDeclaredField("age");
        System.out.println(ageField.getName());

 

         运行结果为:

Java中用反射获取类的属性,方法和构造函数

         得到了Field对象之后,就可以获取到该指定属性的信息了,如属性名,属性权限修饰符等,其实跟获取类的信息的方法是一样的,这里只不过是Field对象调用了而已。

        Field ageField = c.getDeclaredField("age");
        System.out.println(ageField.getName());
        String ageModifier = Modifier.toString(ageField.getModifiers());
        System.out.println(ageModifier);

        运行结果:

Java中用反射获取类的属性,方法和构造函数

         Field对象也可以设置对应传进来的类对象的指定字段的值。使用set(Class c ,Object obj)方法。获取指定的字段值就是用get(Class c)方法; 这个set()方法,只能设置除private以外的值。

        如对Person类设置name的值。

        Object personClass = c.newInstance();
        nameField.set(personClass,"Kiss");
        System.out.println(personClass);

        Object namePerson =  nameField.get(personClass);
        System.out.println(namePerson);

        运行结果为:

Java中用反射获取类的属性,方法和构造函数

三、获取Class对象的方法

         获取Class对象的方法和获取Class对象的属性的方法模式是一模一样的,只不过是将Field改成Method就行,返回也就Method对象/Method对象数组。就不一一多说了。

        另外,值得一提的是,当我们获取的是当个Method对象时,实参要加上该方法的形参的参数类型的Class对象,因为方法会有重载,要在方法名的前提下,也要确定参数的规格。

        

        例如:  获取Person类的方法中的信息

        Class c = Class.forName("com.java.classtest.Person");
        Method [] methods = c.getDeclaredMethods();
        for(Method method:methods) {
            System.out.print("方法名为: "+ method.getName()+",");
            System.out.print("该方法的权限修饰符为: "+Modifier.toString(method.getModifiers()));
            
            System.out.print("该方法的返回类型为:"+method.getReturnType().getSimpleName());
            
            //获取该方法的形参参数的数据类型  简称获取参数类型  
            Class [] parameterTypes = method.getParameterTypes();
            System.out.print("该方法的形参参数类型为: ");
            for( Class parameterType : parameterTypes) {
                System.out.print(parameterType.getSimpleName()+"  ");
            }
            System.out.println();
            
        }

       

        运行结果为:

        Java中用反射获取类的属性,方法和构造函数

         属性可以被设置(set)值,那么方法则可以被调用(invoke) 。我们获得到了一个方法的Method对象,我们就可以通过invoke() 来调用某对象的方法。

        Object objPerson = c.newInstance();
        Method method = c.getDeclaredMethod("setName",String.class);
        method.invoke(objPerson,"Kiss");
        System.out.println(objPerson);

       

运行结果为:

        

Java中用反射获取类的属性,方法和构造函数

四、获取Class对象的构造方法

        构造函数的英语单词为Constructor ,与上述获取方法和属性的使用方法有异曲同工之妙。另外构造方法其实也是方法。所有获取函数方法名,形参参数类型,权限修饰符都是一样的。

        
        Constructor [] constructors = c.getConstructors();
        
        for(Constructor constructor :constructors) {
            System.out.print(Modifier.toString((constructor.getModifiers()))+" ");
            System.out.print(c.getSimpleName()+" ");
            Class [] parameterTypes = constructor.getParameterTypes();
            for(Class parameterType:parameterTypes) {
                System.out.print(parameterType.getSimpleName()+"  ");
            }
            System.out.println();
        }

        运行结果为:

Java中用反射获取类的属性,方法和构造函数

        既然是获取构造函数对象,那么势必是可以调用构造函数的,那无疑就是new一个对象。没错,跟上述的调用无参构造函数一样Class对象可以newInstance()。构造函数对象的话也可以newInstance(),只是这个时候就可以调用有参构造函数了。

        上述的获取字段和方法中,获取的都是某一个准确的字段和方法对象。是一个对象对应一个具体的字段和方法。构造函数也是一样。

        Constructor constructor = c.getConstructor(String.class,int.class);
        Object objPerson = constructor.newInstance("Kiss",20);
        System.out.println(objPerson);

        运行结果为:

        Java中用反射获取类的属性,方法和构造函数

打赏
文章版权声明:除非注明,否则均为彭超的博客原创文章,转载或复制请以超链接形式并注明出处。
相关推荐

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

猜你喜欢