java中的反射

java中的反射

反射(Refection)就是加载类,并允许以编程方式解剖类中的各种成分(成员变量,方法,构造器…)

步骤

  1. 加载类,获取类或类型的字节码:Class对象
  2. 获取类的构造器:Constructor对象
  3. 获取类的成员变量:Field对象
  4. 获取类的成员方法:Method对象

加载类

加载类一般有三种方式

  1. 类名.class的方式获取

    Class a=String.class;
    Class b=Arrays.class;
    Class c=char.class;
    Class d=int[].class
    

    此方法一般用于获取常见类,官方(或外部jar包)提供类或类型的Class对象

  2. 调用Class提供的forName静态方法

    原型:Class.forName(全类名)

    Class a=Class.forName("com.gezishan.refection.Teacher");
    Class b=Class.forName("com.gezishan.refection.Student");
    //已在对应包创建对应类
    
  3. 调用Object提供的getClass方法(已继承到所有的类的对象)

    Class a=teacher.getClass();
    class b=stydent.getClass();
    

    此方法常用于获取具体的某个对象的Class对象。是最常用的获取Class对象的方法

Class类的常用方法

方法 描述
String getName() 获取全类名
String getSimpleName() 获取简名(类名)
Constructor[] getConstructors() 获取全部公开构造器(public修饰)
Constructor[] getDeclaredConstructors() 获取全部构造器
Constructor getConstructor(Class…parTypes) 获取某个指定参数列表的公开构造器,没有则是无参构造器
Constructor getDeclaredConstructor(Class…parTypes) 获取某个指定参数列表的构造器,没有则是无参构造器
Field[] getFields() 获取全部公开的成员变量
Field[] getDeclaredFields() 获取全部的成员变量
Filed getfield(String name) 获取某个公开的成员变量
Filed getDeclaredfield(String name) 获取某个成员变量
Method[] getMethds() 获取全部公开的成员方法
Method[] getDeclaredMethods() 获取全部成员方法
Method getMethods(String name,Class…par) 获取名为name,参数列表为pre的公开的成员方法
Method getDeclaredMethods(String name,Class…par) 获取名为name,参数列表为pre的成员方法
boolean isArray() 判断是否为数组
boolean isEnum() 判断是否为枚举类
isInterface() 判断是否为接口
isPrimitive() 判断是否为基本类型
isSynthetic() 判断是否为合成类(在一个类中创建另一个类)

Constructor类的常用方法

方法 描述
void setAccessible(boolean flag) 设置是否检查访问控制
T newInstance(OBject…initargs) 调用此构造器并传入参数,完成对象创建并返回
String getName() 以字符串方式放回此构造器的名称

注:

当此构造器定义成非公开的时,只有 setAccessible(boolean flag)中的flag设置为true时(称暴力反射),才能利用此构造器进一步操作,如使用newInstance()创建对象。后面的FieldMethod也类似.

Field类的常用方法

方法 描述
String getName() 获取成员变量名
Class getType() 获取成员变量类型
void setAccessible(boolean flag) 设置是否检查访问控制
Object get(Object obj) 获取实例obj的该成员变量的值
void set(Object obj,Object value) 修改实例obj的该成员变量的值为value

Method类的常用方法

方法 描述
String getName() 获取成员方法名
void setAccessible(boolean flag) 设置是否检查访问控制
int getParameter() 获取方法参数个数
Class getRecturnType() 获取返回值类型
Object invoke(OBject obj,OBject…args) 触发执行实例obj执行该方法,orgs为参数列表

反射的作用

  1. 在类的外部得到一个类的全部成员后操作
  2. 破坏了封装性
  3. 常用于做java框架

反射微架构

对象转json格式字符串

需求描述

设计一个Tojson类,里面的tojson(OBject obj)方法可实现将对象obj的所有成员变量封装到一个json格式字符串中。

例:

public class Student {
    private String name;
    private int age;
    private boolean gender;
    private int score;
    
    public Student() {
    }
    public Student(String name, int age, boolean gender, int score) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.score = score;
    }
}

调用Tojson.tojson(new Student("张三",20,true,90))后的返回结果字符串

{"name":"张三","age":20,"gender":true,"score":90}

需求分析

首先对json格式的字符串做个明确的定义:

  1. json数据用一对{}括起来
  2. 数据采用键值对表示,键与值之间用 逗号, 分割
  3. 键用双引号""括起来
  4. 值可以是一个变量,数组,json格式对象,空值
    1. 变量,是字符串的话,也用双引号""括起来,否则不用
    2. 数组,用[]括起来,元素变量之间用逗号,分割
    3. json格式对象,相当于嵌套,同样遵循json格式规则
    4. 空值,null

1.简单的实体类(成员变量都是简单类型)的json格式转换:

public class ToJson {
    public static String tojson(Object obj) throws Exception {
        StringBuilder json = new StringBuilder("{");  //StringBuilder比String更适合做字符串追加等操作
        Class tar=obj.getClass();  //常用
        Field[] fields=tar.getDeclaredFields();  //获取所有成员变量列表
        boolean flat=false;
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);  //设置不检查访问控制
            json.append("\"");
            json.append(fields[i].getName());
            json.append("\":");
            if(fields[i].get(obj)!=null){
                if(fields[i].getType()!=String.class) json.append(fields[i].get(obj));
                else{
                    json.append("\"");
                    json.append(fields[i].get(obj));
                    json.append("\"");
                }
            }
            else{
                json.append("null");
            }
            if(i<fields.length-1) json.append(",");
        }
        json.append("}");
        return json.toString();
    }
}
  1. 成员变量包含数组的json格式转换
public class ToJson {
    public static String tojson(Object obj) throws Exception {
        StringBuilder json = new StringBuilder("{");  //StringBuilder比String更适合做字符串追加等操作
        Class tar=obj.getClass();  //常用
        Field[] fields=tar.getDeclaredFields();  //获取所有成员变量列表
        boolean flat=false;
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);  //设置不检查访问控制
            json.append("\"");
            json.append(fields[i].getName());
            json.append("\":");
            if(fields[i].get(obj)!=null){
                if(fields[i].getType()==String.class){  //字符串类型
                    json.append("\"");
                    json.append(fields[i].get(obj));
                    json.append("\"");
                }
                else if(fields[i].getType().isArray()){  //数组类型
                    json.append("[");
                    int len=Array.getLength(fields[i].get(obj));  //获取数组长度
                    for (int j = 0; j < len; j++) {
                        Object val=Array.get(fields[i].get(obj), j);  //获取数组第j个变量
                        if(val.getClass()==String.class){  //字符串类型
                            json.append("\"");
                            json.append(String.valueOf(val));
                            json.append("\"");
                        }
                        else{
                            json.append(String.valueOf(val));
                        }
                        if(j<len-1) json.append(",");
                    }
                    json.append("]");
                }
                else{
                    json.append(fields[i].get(obj));
                }
            }
            else{
                json.append("null");
            }
            if(i<fields.length-1) json.append(",");
        }
        json.append("}");
        return json.toString();
    }
}
  1. 复杂类(成员变量为类对象)的json格式转换

    复杂类涉及到类的嵌套,这需要递归实现,还涉及类的类型判断等,本篇文章作为反射的入门学习就不深入下去了。对于将实体类对象转换为json格式字符串的API可参见spring框架和阿里巴巴的fastJson。

你可能感兴趣的:(java,开发语言)