【初闻反射】

求关注 求支持

1

Java反射机制

Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象、调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展

通过反射使用一个类

事先建立好的Student类
我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象 ,也就是类型为Cass类型的对象
这里我们提供三种方式 获取Class类型的对象
使用类的class属性来获取该类对应的Class对象。举例:Student.class将会返回Student类对应的Class对象

 //使用类的Class属性
        Class<Student> c1 = Student.class;
        System.out.println(c1);//输出Student地址

        Class<Student> c2 = Student.class;
        System.out.println(c1==c2);

调用对象的getClass()方法,返回该对象所属类对应的Class对象该方法是Object类中的方法,所有的Java对象都可以调用该方法

 //调用对象的getClass方法
        Student s=new Student();
        Class<? extends Student> c3 = s.getClass();
        System.out.println(c3==c1);

使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径

 //使用Class类中的静态方法ForName
        Class<?> c4 = Class.forName("FanSe.GetClassDemo.Demo_01.Student");
        System.out.println(c4==c1);

使用反射获取构造方法并使用

//首先获取class对象
        Class<?> c = Class.forName("FanSe.GetClassDemo.Demo_01.Student");

        //获取公共的构造函数数组
        Constructor<?>[] cons = c.getConstructors();
        for(Constructor con:cons){
            System.out.println(con);
        }
        System.out.println("_______________________________");
        //获取全部构造方法数组
        Constructor<?>[] constructors = c.getDeclaredConstructors();
        for(Constructor con:constructors){
            System.out.println(con);
        }

        System.out.println("_______________________________");
        //获取单个公共构造函数
        Constructor<?> con = c.getConstructor();
            //映射输出构造函数
        Object obj = con.newInstance();
        System.out.println(obj);
            //正常输出构造函数
        Student s=new Student();
        System.out.println(s);

成员变量也可以获取Class在赋值时要一一对应

Class<?> c = Class.forName("FanSe.GetClassDemo.Demo_01.Student");

        Constructor<?> constructor = c.getConstructor(String.class, int.class, String.class);
        Object obj = constructor.newInstance("XX", 20, "火星");
        System.out.println(obj);

对于私有的构造函数,我们可以用 getDeclaredConstructor获取,但映射时会抛出异常,无法对私有的进行赋值,我们可以使用暴力反射 setAccessible(true)

 Class<?> c = Class.forName("FanSe.GetClassDemo.Demo_01.Student");

        //Constructor<?> constructor = c.getConstructor(String.class);
        //Object obj = constructor.newInstance("XX");
        //System.out.println(obj);
        //私有方法,不可以用上面的方式
        Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class);

        //暴力反射,值为true取消权限检查
        declaredConstructor.setAccessible(true);

        Object obj = declaredConstructor.newInstance("XX");
        System.out.println(obj);

通过反射获取成员变量并使用

Class<?> c = Class.forName("FanSe.GetClassDemo.Demo_01.Student");

        //获取公共的成员变量数组
        //Field[] fields = c.getFields();

        //获取全部的成员变量的数组
        Field[] fields = c.getDeclaredFields();
        for(Field field:fields){
            System.out.println(field);
        }

        //获取公共的单个成员变量
        Field addressField = c.getField("address");//要获取公共变量的名称

            //正常使用
            Student s=new Student();
            s.address="中国";
            System.out.println(s);

            //映射使用
            //获取无参构造函数
            Constructor<?> con = c.getConstructor();
            Object obj = con.newInstance();

            //使用set方法,将obj对象的address赋值为中国
            addressField.set(obj,"中国");
            System.out.println(obj);

与获取构造方法相似,有四种获取方式但在赋值上,有一个 set方法

		Field address = c.getField("address");
        Field name = c.getDeclaredField("name");
        Field age = c.getDeclaredField("age");
//通过无参构造函数获取obj对象,将成员变量赋值给obj中对应的数据
        Constructor<?> con=c.getConstructor();
        Object obj = con.newInstance();
//对于非公有方法,先用暴力反射对其权限修改
        name.setAccessible(true);
        age.setAccessible(true);
        address.set(obj,"中国");
        name.set(obj,"XX");
        age.set(obj,12);

通过反射获取成员方法并使用

  Class<?> c = Class.forName("FanSe.GetClassDemo.Demo_01.Student");

        //获取公共的方法,包含继承的方法
        //Method[] methods = c.getMethods();

        //获取全部的方法
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //获取单个方法
        Method method1 = c.getMethod("method1");//两个参数,方法名,方法需要的参数(这个是无参方法)

            //获取无参构造获取对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

            method1.invoke(obj);//两个参数(该方法无参方法)

        System.out.println(obj);
Class<?> c = Class.forName("FanSe.GetClassDemo.Demo_01.Student");

        //获取无参构造
        //Student s=new Student();与普通用法中,构建Student对象类似
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

        //获取方法
        Method method1 = c.getMethod("method1");
        Method method2 = c.getMethod("method2", String.class);
        Method method3 = c.getMethod("method3", String.class, int.class);

        method1.invoke(obj);

        method2.invoke(obj,"薛俊");

        Object o = method3.invoke(obj, "薛俊", 23);
        System.out.println(o);


        //获取私有方法
        Method method = c.getDeclaredMethod("function");
        //暴力反射
        method.setAccessible(true);
        method.invoke(obj);

反射作用小练习1

在Integer类型的数组中添加“java牛皮”

 ArrayList<Integer> arrayList=new ArrayList<Integer>();

        arrayList.add(1);
        arrayList.add(2);
        //arrayList.add("Java牛皮");❌

        System.out.println(arrayList);

这里普通添加无法实现,但利用反射可以实现,还可以调用私有方法

		ArrayList<Integer> arrayList=new ArrayList<Integer>();

        arrayList.add(1);
        arrayList.add(2);
        //arrayList.add("Java牛皮");❌
		//利用反射添加字符串
            //获取Class,这里已有对象,不需要建立无参构造
       		 Class<? extends ArrayList> c = arrayList.getClass();

       		 Method add = c.getMethod("add", Object.class);
        	 add.invoke(arrayList,"Java牛皮");

       		 System.out.println(arrayList);

跪谢查阅
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小橙菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值