Java反射实现存储任意对象属性的小例子

相关概念:
反射:Java独有的技术
作用:对于任何一个类,在运行时都可以直接得到这个类的全部成分
构造器对象Constructor,成员变量对象Filed,成员方法对象Method
核心思想:得到编译后的class文件对象
注意:反射是工作在运行时的技术,因为只有在运行后才有class类对象

反射的第一步永远是先得到Class类对象,有3种方式
    (1)类名.class
    (2)通过类的对象.getClass()
    (3)Class.forName("类的全限定名")

获取构造器:
    public Constructor<T> getConstructor(Class<?>... parameterTypes) 根据参数匹配获取某个构造器,只能获取public修饰的构造器
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 根据参数匹配获取某个构造器,不关心权限修饰符
    public Constructor<?>[] getConstructors() 获取全部构造器,只能是public修饰
    public Constructor<?>[] getDeclaredConstructors() 获取全部构造器,不关心权限修饰符

构造器初始化对象方法:
    public T newInstance(Object ... initargs) 调用无参数构造器,已弃用
    public void setAccessible(boolean flag) 修改访问权限,单次有效

获取成员变量:
    public Field getField(String name) 根据成员变量名获取对应Field对象,只能获取public修饰,包括父类
    public Field getDeclaredField(String name) 根据成员变量名获取对应Field对象,只要定义就能获取
    public Field[] getFields()  获取所有成员变量的Field对象,只能获取public修饰,包括父类
    public Field[] getDeclaredFields() 获取所有成员变量的Field对象,只要定义就能获取

成员变量的方法:
    public void set(Object obj, Object value) 设置obj的成员变量值为value
    public Object get(Object obj) 获取obj的成员变量值
    public void setAccessible(boolean flag) 修改访问权限
    public Class<?> getType() 获取成员变量的类型
    public String getName() 获取成员变量名称

获取方法
    public Method getMethod(String name,Class<?>... parameterTypes) 根据方法名和参数获取对应Method对象,只能获取public修饰,包括父类
    public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 根据方法名和参数获取对应Method对象,只要定义就能获取
    public Method[] get Methods()  获取所有方法的Method对象,只能获取public修饰,包括父类
    public Method[] getDeclaredMethods() 获取所有方法的Method对象,只要定义就能获取
Method相关方法:
    public Object invoke(Object obj, Object... args) 使obj对象执行某方法,没有返回值返回null

反射可以破坏面向对象的封装性,同时可以破坏泛型的约束性(泛型只能工作在编译阶段)

要存储的Student类:

class Student{
    private String name;
    private int age;
    private char sex;

    public Student(String name, int age, char sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

存储方法和测试方法:

public class ReflectDemo {

    public static void main(String[] args) throws Exception {
        Student student = new Student("kobe", 40, '男');
        save(student);
    }

    public static void save(Object obj){
        try(PrintStream ps=new PrintStream(new FileOutputStream("heima/src/day12_junit_反射_注解_代理/data.txt"),true)){
            //获取Class对象
            Class<?> clazz = obj.getClass();
            ps.println("---------"+clazz.getSimpleName()+"---------");
            //获取所有成员变量
            Field[] fields = clazz.getDeclaredFields();
            for(Field field:fields){
                //成员变量名
                String fieldName = field.getName();
                //成员变量对应的get方法名称=get+首字母大写的成员变量名
                String methodName="get"+fieldName.toUpperCase().substring(0,1)+fieldName.substring(1);
                Method method = clazz.getDeclaredMethod(methodName);
                //成员变量对应的值
                Object value = method.invoke(obj);
                //save
                ps.println(fieldName+"="+value);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

结果:
在这里插入图片描述

发布了66 篇原创文章 · 获赞 302 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_41112238/article/details/105004342