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

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

1、Class.forName(全类名)

2、类名.class

3、对象.getClass()

实现代码如下:

java 复制代码
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);
java 复制代码
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修饰的空参构造 ,所以创建出来的也是一个没有参数的对象

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

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

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

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

利用反射获取成员变量

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

java 复制代码
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。

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

反射练习(一)

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

学生Student类

java 复制代码
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类

java 复制代码
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 + "}";
    }
}

反射代码执行类

java 复制代码
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();
    }
}

反射总结:

动态代理 (初始了解)

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

相关推荐
远望清一色1 分钟前
基于MATLAB边缘检测博文
开发语言·算法·matlab
何曾参静谧9 分钟前
「Py」Python基础篇 之 Python都可以做哪些自动化?
开发语言·python·自动化
Prejudices13 分钟前
C++如何调用Python脚本
开发语言·c++·python
Daniel 大东14 分钟前
idea 解决缓存损坏问题
java·缓存·intellij-idea
wind瑞20 分钟前
IntelliJ IDEA插件开发-代码补全插件入门开发
java·ide·intellij-idea
HappyAcmen20 分钟前
IDEA部署AI代写插件
java·人工智能·intellij-idea
马剑威(威哥爱编程)26 分钟前
读写锁分离设计模式详解
java·设计模式·java-ee
我狠狠地刷刷刷刷刷26 分钟前
中文分词模拟器
开发语言·python·算法
鸽鸽程序猿26 分钟前
【算法】【优选算法】前缀和(上)
java·算法·前缀和
修道-032327 分钟前
【JAVA】二、设计模式之策略模式
java·设计模式·策略模式