Java学习记录(二十二)反射,动态代理

反射获取class对象的三种方式

1、Class.forName(全类名)

2、类名.class

3、对象.getClass()

实现代码如下:

package com.itazhang.Demo1;

public class MyReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种获取class对象的方法
        Class clazz1 = Class.forName("com.itazhang.Demo1.Student");
        //第二种直接用对象去调用getClass
        Student stu = new Student();
        Class clazz2 = stu.getClass();
        //第三种方法
        Class clazz3 = Student.class;
    }
}

反射获取构造方法

在利用class对象获取相关构造方法的步骤如下:先用Class.forname方法创建相应的class对象 ,再通过class对象调用相关的方法,有declared修饰的方法就能获取所有修饰符的构造方法,最后带s的是返回所有相关构造方法,而没有带s的只返回一个,例如:需要传递相应的类型参数得到相应参数的构造方法,如空参构造就不传递,两个的带参构造就传递这两个数据类型的字节码

Constructor constructor = clazz.getConstructor();
Constructor constructor1 = clazz.getConstructor(String.class, int.class);
package com.itazhang.Demo1;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class MyReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName("com.itazhang.Demo1.Student");
        //获取所有public修饰的构造方法
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("----------------------------");
        //获取所有修饰符的构造方法
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("------------------------------");
        //获取单个public修饰的构造方法,传递相应的参数即可
        Constructor constructor = clazz.getConstructor();
        System.out.println(constructor);

        //创建public修饰的构造方法的对象
        Student stu1 = (Student) constructor.newInstance();
        System.out.println(stu1);

        System.out.println("-----------------1------------------");

        Constructor constructor1 = clazz.getConstructor(String.class, int.class);
        System.out.println(constructor1);
        //获取单个所有修饰符的构造方法
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor);

        //创建private修饰的对象
        declaredConstructor.setAccessible(true);
        Student stu =(Student) declaredConstructor.newInstance("张三");
        System.out.println(stu);
    }
}

获取了构造方法之后就能通过获取出来的对象调用newInstance方法创建相关构造方法的对象,但是要注意参数个数和类型得与构造方法中的一致,如下:这是一个public修饰的空参构造 ,所以创建出来的也是一个没有参数的对象

//获取单个public修饰的构造方法,传递相应的参数即可
        Constructor constructor = clazz.getConstructor();
        System.out.println(constructor);

        //创建public修饰的构造方法的对象
        Student stu1 = (Student) constructor.newInstance();
        System.out.println(stu1);

而如果获取了private等私有修饰符的构造方法,如果需要用该构造方法,需要在创建对象之前使用setAccessible方法给此方法传递true,然后才能使用私有修饰符修饰的构造方法创建对象,如下:

//创建private修饰的对象
        declaredConstructor.setAccessible(true);
        Student stu =(Student) declaredConstructor.newInstance("张三");
        System.out.println(stu);

利用反射获取成员变量 

获取成员方法大致与获取构造方法相同,也是先创建相关类的Class对象,利用Class.forName获取class对象,如果想获取一个public修饰的成员变量就用getField方法,如果想获取其他修饰符的成员方法就用getDeclaredField方法,同样的如果想使用私有修饰符修饰的成员变量的话得调用setAccecible方法且传递true之后才能使用私有的成员方法,如下:

package com.itazhang.Demo2;

import java.lang.reflect.Field;

public class MyReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class clazz = Class.forName("com.itazhang.Demo2.Student");
        //获取全部成员变量
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-----------1-----------");
        //获取单个public修饰的成员变量
        Field gender = clazz.getField("gender");
        System.out.println(gender);
        System.out.println("------------2---------");
        //获取全部修饰符的成员变量
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("------------3-----------");
        //获取单个所有修饰符的成员变量
        Field age = clazz.getDeclaredField("age");
        System.out.println(age);

        System.out.println("------------4------------");
        //使用private修饰符的成员变量
        Student stu = new Student("azhang",22,"男");
        age.setAccessible(true);
        Object o = age.get(stu);
        System.out.println(o);
    }
}

反射获取成员方法

大致方法的使用与之前获取成员方法相同,但是如果要使用获取出的方法时,需要用获取出来的对象调用invoke方法,传入调用该获取出来方法的对象 ,和方法需要传递的参数,这样就能使用获取出的方法,代码如下:Student类中有一个private修饰的eat方法,该方法有一个返回值且是private修饰的方法,使用invoke方法会有一个返回值,该返回值就是使用的方法的返回值,如果没有返回值,默认返回null。

//获取方法
        Student s = new Student();
        Method eat = clazz.getDeclaredMethod("eat", String.class);
        eat.setAccessible(true);
        Object o1 = eat.invoke(s, "面条");
        System.out.println(o1);

反射练习(一)

通过反射获取到两个不同类里的相关属性,且将这两个类对象的属性值写入到本地文件中

学生Student类

package com.itazhang.Demo3;

public class Student {
    private String name;
    private int age;
    private String gender;
    private String address;

    public Student() {
    }

    public Student(String name, int age, String gender, String address) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.address = address;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    /**
     * 获取
     * @return address
     */
    public String getAddress() {
        return address;
    }

    /**
     * 设置
     * @param address
     */
    public void setAddress(String address) {
        this.address = address;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}";
    }
}

老师Teacher类

package com.itazhang.Demo3;

public class Teacher {
    private String name;
    private int salary;

    public Teacher() {
    }

    public Teacher(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return salary
     */
    public int getSalary() {
        return salary;
    }

    /**
     * 设置
     * @param salary
     */
    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String toString() {
        return "Teacher{name = " + name + ", salary = " + salary + "}";
    }
}

反射代码执行类

package com.itazhang.Demo3;

import java.io.*;
import java.lang.reflect.Field;

public class MyReflectDemo3 {
    public static void main(String[] args) throws IllegalAccessException, IOException {

        Student stu = new Student("azhang",22,"男","chengdu");
        Teacher tch = new Teacher("ahuai",12000);
        saveObject(stu);
        saveObject(tch);
    }

    public static void saveObject(Object obj) throws IllegalAccessException, IOException {

        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\11Codingtext\\MyReflect\\a.txt",true));
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            Object value = field.get(obj);
            System.out.println(name + "=" + value);
            bw.write(name+"="+value);
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

反射总结:

动态代理 (初始了解)

能实现无侵入式的给代码增加额外的功能。

  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值