通过反射调用运行时类的各种属性

反射:

反射是动态语言的关键,反射机制运行java在执行期间,借助Reflection提供的API取得任何类的内部信息,
并能直接操作任意对象的内部属性与方法
本文只是自学菜鸟的一些总结,菜得很,希望大佬的指正和纠错

供以下程序操作的Person类

package java1;

@MyAnnotatino(value = "hi")
public class Person extends Creature<String> implements Comparable<String>,Myinterface{
    
    
    private String name;
    int age;
    public int id;


    @MyAnnotatino(value = "abc")
    public Person() {
    
    
    }
    @MyAnnotatino
    private Person(String name){
    
    
        this.name = name;
    }

    @MyAnnotatino
    public String getName() {
    
    
        return name;
    }

    private String show(String nation){
    
    
        System.out.println("我的国籍是" + nation);
        return nation;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }
    @MyAnnotatino
    public int getAge() {
    
    
        return age;
    }
    @MyAnnotatino(value = "hi")
    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String display(String interests){
    
    
        return interests;

    }
    @Override
    public void myvoid() {
    
    
        System.out.println("一个人");
    }


    @Override
    public int compareTo(String o) {
    
    
        return 0;
    }

    public static void main(String[] args) {
    
    
        ReflectionTest.Person p1 = new ReflectionTest.Person();
        System.out.println();
    }

    private static void showDesc(){
    
    
        System.out.println("我是一个人");
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                '}';
    }
}

通过反射调用运行时类的属性

其实通过反射调用运行时类的各种属性的步骤都是一样的,只是各个方法名不同。
以获取类中的属性为例:

Class clazz = Person.class;
       //获取所有属性结构:getFields
        Field[] field = clazz.getFields();
        for (Field f:field){
    
    
            System.out.println(f);
        }
        //getDeclaredFiels:获取运行时类自己声明过的属性,不考虑权限,不包含父类中声明的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        //用增强for循环输出
        for (Field f:declaredFields){
    
    
            System.out.println(f);
        }

通过反射获取运行时类的各种权限修饰符,方法,注解等等

其实步骤和上面是一样的,只是有一些细微的差距

//获取权限修饰符
 Class clazz = Class.forName("java1.Person");
        Field[] df = clazz.getDeclaredFields();
        for (Field f:df){
    
    
            //权限修饰符:getModifiers,获取权限修饰符,int类型:0:default,1:public,2:private,3:protected
            //将int型权限修饰符变为字符串形式:Modifier.toString
            System.out.println(Modifier.toString(f.getModifiers()));
            //数据类型:getType
            System.out.println(f.getType().getName());
            //变量名:getname:获取变量名
            System.out.println(f.getName());

//获取方法声明的注解,形参列表,异常,形参名等

     Class<Person> clazz = Person.class;
        Method[] me = clazz.getDeclaredMethods();
        for (Method m:me){
    
    
            //getAnnotations:获得当前方法的所有注解
            Annotation[] ann = m.getAnnotations();
            for (Annotation a:ann){
    
    
                System.out.println("注解为"+a);
            }
            System.out.println(Modifier.toString(m.getModifiers()) );
            //返回值类型returnType:返回型类型的名字:getName
            Class<?> returnType = m.getReturnType();
            System.out.println(returnType.getName());
            //方法名:getName:通常情况方法名后会配合形参列表
            System.out.print(m.getName());
            System.out.print("(");
            //形参列表:获取形参类型方法:getParameterTypes
            //获取形参名:
            Class<?>[] types = m.getParameterTypes();
            if (!(types == null&& types.length == 0)){
    
    
                for (int i= 0;i<types.length;i++){
    
    
                    //获取形参名,如果形参是最后一个,就不加逗号
                    if (i == types.length-1){
    
    
                        System.out.print(types[i].getName()+"args_"+i);
                        break;
                    }
                    System.out.print(types[i].getName()+"args_"+i+",");

                }
                System.out.print(")");
                //抛出的异常:getExceptionTypes
                Class<?>[] ex = m.getExceptionTypes();
                if (!(ex == null&&ex.length ==0)){
    
    
                    System.out.println("throws");
                    for (int i =0;i<ex.length;i++){
    
    
                        if (i == ex.length-1){
    
    
                            System.out.println(ex[i].getName());
                            break;
                        }
                        System.out.println(ex[i].getName() + "i");
                    }
                }
            }
            //
            System.out.println("*********");


        }



    }
}

通过反射操作运行时类的属性,方法

操作属性方法时,一般使用getdeclared的相关方法,因为此类方法可以调用任何权限修饰符的方法属性
其中的关键方法为:setAccessible(),将形参填入true时,就可以保证属性和方法的修改和访问

 public void Test2() throws Exception {
    
    
        Class<Person> clazz = Person.class;
        Person p = clazz.newInstance();
        //getDeclaredField(String name)
        Field name = clazz.getDeclaredField("name");
        //为了避免出现非法访问的情况,必须在设置之前进行setAccessible方法,保证当前属性是可访问的
        name.setAccessible(true);//保证当前属性时可访问的
        name.set(p,"ljy"); //此时出现IllegalAccessException:非法访问,即文件找到了但是没有权限访问
        System.out.println(name.get(p));


    }

总结

通过反射操作运行时类中的属性方法步骤其实都是一样的
1.获取运行时类的class。
2.创建运行时类的对象(供非static的结构使用)
3.调用目标类型的get或getdeclared方法
4.需要操作时,为了确保可访问,调用setAccessible方法
5.调用set,get等方法进行操作

猜你喜欢

转载自blog.csdn.net/qq_52873070/article/details/113779914