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

反射:

反射是动态语言的关键,反射机制运行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等方法进行操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值