一、反射概念

java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为java语言的反射机制。反射被视为动态语言的关键。

二、反射应用场景

1.几乎所有的框架都会用到反射

2.程序解耦合使用

3.代码更加的优雅

三、反射更多细节

1.jdk中的位置: java.lang.reflect包下

2.获取字节码方式

// 通过类的全限定类名获取
class<?> clazza = class.forname("com.open_source.demo.domain.hero");
// 通过类直接获取
class<hero> clazzb = hero.class;
// 通过实例化对象获取
class<? extends hero> clazzc = (new hero()).getclass();
// 基本类型的包装类的type获取
class<byte> byteclazz = byte.type;
class<short> typeclazz = short.type;
class<integer> integerclazz = integer.type;
class<long> longclazz = long.type;
class<float> floatclazz = float.type;
class<double> doubleclazz = double.type;
class<character> characterclazz = character.type;
class<boolean> booleanclazz = boolean.type;

3.测试类hero省略setter和getter以及tostring方法其中包含无参构造和满参构造

package com.open_source.demo.domain;

/**
 * 英雄实体类
 *
 * @author: tyvek
 */
public class hero {
    /**
     * 类型
     */
    private string type;
    /**
     * 姓名
     */
    private string name;
    /**
     * 战力
     */
    private double ce;

    /**
     * 打印英雄属性
     *
     * @param hero 英雄对象
     */
    public void attrbute(hero hero) {
        system.out.println(hero.gettype() + ": " + hero.getname() + "输出伤害: " + hero.getce());
    }

    /**
     * 为队友加油
     */
    public void fighting() {
        system.out.println("稳住 我们能赢");
    }

    /**
     * 向英雄发起进攻
     *
     * @param name 英雄名字
     */
    public void attack(string name) {
        system.out.println("准备向" + name + "发起进攻");
    }

    public hero(string type, string name, double ce) {        
        this.type = type;
        this.name = name;
        this.ce = ce;
    }

    public hero() {
    }
}

4.获取类的成员

获取类的构造函数

import java.util.stringjoiner;

/**
 * 反射测试类
 * @author: tyvek
 */
public class reflectclient {
    public static void main(string[] args) throws classnotfoundexception {
        // 通过类的全限定类名获取
        class<?> clazza = class.forname("com.open_source.demo.domain.hero");
        // 获取所有构造函数字节码
        constructor<?>[] declaredconstructors = clazza.getdeclaredconstructors();
        // 打印构造函数修饰符以及参数类型
        for (int i = 0; i < declaredconstructors.length; i++) {
            // 美化输出
            stringjoiner sj = new stringjoiner(", ","[","]");
            system.out.print("构造函数修饰符:" + modifier.tostring(declaredconstructors[i].getmodifiers()) + "  参数类型:");
            class<?>[] parametertypes = declaredconstructors[i].getparametertypes();
            for (int j = 0; j < parametertypes.length; j++) {
                sj.add(parametertypes[j].getname());
            }
            system.out.println(sj.tostring());
        }
    }
}
// 打印内容  
构造函数修饰符:public  参数类型:[java.lang.string, java.lang.string, java.lang.double] 
构造函数修饰符:public  参数类型:[]		

获取指定构造函数

// 通过类的全限定类名获取
class<?> clazza = class.forname("com.open_source.demo.domain.hero");
// 获取满参构造
constructor<?> allargsconstructor = clazza.getdeclaredconstructor(string.class, string.class, double.class);
// 获取无参构造
constructor<?> noneargconstructor = clazza.getdeclaredconstructor();

调用构造函数

public class reflectclient {
    public static void main(string[] args) throws classnotfoundexception, nosuchmethodexception, illegalaccessexception, invocationtargetexception, instantiationexception {
        // 通过类的全限定类名获取
        class<?> clazza = class.forname("com.open_source.demo.domain.hero");
        // 获取满参构造
        constructor<?> allargsconstructor = clazza.getdeclaredconstructor(string.class, string.class, double.class);
        // 获取无参构造
        constructor<?> noneargconstructor = clazza.getdeclaredconstructor();
        // 如果修饰符为private需要使用暴力反射
        // noneargconstructor.setaccessible(true);
        hero hero = (hero) noneargconstructor.newinstance();
        hero.settype("射手");
        hero.setname("后裔");
        hero.setce(1000.0);
        system.out.println(hero);
        hero heroall = (hero) allargsconstructor.newinstance("法师", "诸葛亮", 1000.1);
        heroall.attrbute(heroall);
    }
}
// 控制台输出
hero{type='射手', name='后裔', ce=1000.0}
法师: 诸葛亮 输出伤害: 1000.1

获取成员方法

public class reflectclient {
    public static void main(string[] args) throws classnotfoundexception, nosuchmethodexception, illegalaccessexception, invocationtargetexception, instantiationexception {
        // 通过类的全限定类名获取
        class<?> clazza = class.forname("com.open_source.demo.domain.hero");
        // 获取无参构造
        constructor<?> noneargconstructor = clazza.getdeclaredconstructor();
        hero hero = (hero) noneargconstructor.newinstance();
        // 获取所有成员方法
        method[] declaredmethods = clazza.getdeclaredmethods();
        for (int i = 0; i < declaredmethods.length; i++) {
            stringjoiner sj = new stringjoiner(",", "[", "]");
            system.out.print("方法名称:" + declaredmethods[i].getname() + " 方法参数: ");
            class<?>[] parametertypes = declaredmethods[i].getparametertypes();
            for (int j = 0; j < parametertypes.length; j++) {
                sj.add(parametertypes[j].getname());
            }
            system.out.println(sj.tostring());
        }
    }
}
// 控制台输出
方法名称:attrbute 方法参数: [com.open_source.demo.domain.hero]
方法名称:attack 方法参数: [java.lang.string]
set和get省略

方法调用

// 获取attack字节码对象
method attackmethod = clazza.getdeclaredmethod("attack", string.class);
// 如果修饰符为private同样需要使用暴力反射
attackmethod.invoke(hero,"周瑜");
// 控制台输出
准备向周瑜发起进攻

获取所有的成员属性

public class reflectclient {
    public static void main(string[] args) throws classnotfoundexception, nosuchmethodexception, illegalaccessexception, invocationtargetexception, instantiationexception {
        // 通过类的全限定类名获取
        class<?> clazza = class.forname("com.open_source.demo.domain.hero");
        // 获取所有成员属性
        field[] declaredfields = clazza.getdeclaredfields();
        stream.of(declaredfields).foreach(system.out::println);
    }
}
// 控制台输出
private java.lang.string com.open_source.demo.domain.hero.type
private java.lang.string com.open_source.demo.domain.hero.name
private java.lang.double com.open_source.demo.domain.hero.ce

获取父类的字节码

// 通过类的全限定类名获取
class<?> clazza = class.forname("com.open_source.demo.domain.hero").getsuperclass();

反射工具类

package com.open_source.demo.support;

import java.lang.reflect.field;
import java.lang.reflect.method;
import java.math.bigdecimal;
import java.text.simpledateformat;
import java.util.arraylist;
import java.util.arrays;
import java.util.date;
import java.util.list;

/**
 * @author: tyvek
 * 反射工具类
 */
public class reflectsupport {
    private reflectsupport(){};

    /**
     * 获取字段对应值,并转为string类型,空值返回空字符串
     * @param fieldname
     * @param obj
     * @return
     */
    public static synchronized string getstringvalue(string fieldname,object obj) throws  reflectiveoperationexception{
        object objectvalue = getvaluebygetter(fieldname,obj);
        if (objectvalue == null){
            return "";
        }
        string result = objectvalue.tostring();
        //如果类型为bigdecimal,去掉末尾的0
        if (objectvalue instanceof bigdecimal){
            bigdecimal value = (bigdecimal) objectvalue;
            value = value.striptrailingzeros();
            result = value.toplainstring();
        }else if (objectvalue instanceof date){
            simpledateformat sdf = new simpledateformat("yyyy-mm-dd hh:mm:ss");
            result = sdf.format((date)objectvalue).replace(" 00:00:00", "");
        }

        return result.trim();
    }

    public static object getvaluebygetter (string fieldname,object obj) throws reflectiveoperationexception {
        method getter = getgetter(fieldname, obj.getclass());
        if (getter != null){
            return getter.invoke(obj);
        }

        return null;
    }


    public static object setvaluebysetter (string fieldname,object obj) throws reflectiveoperationexception {
        method setter = getsetter(fieldname, obj.getclass());
        if (setter == null){
            throw new reflectiveoperationexception("没有set方法");
        }

        return setter.invoke(obj);
    }

    /**
     * 获取get方法
     * @param fieldname
     * @param cls
     * @return
     */
    public static method getgetter(string fieldname,class<?> cls){
        for (method method : cls.getmethods()) {
            if (method.getname().equalsignorecase("get".concat(fieldname)) && method.getparametertypes().length == 0){
                return  method;
            }
        }
        return null;
    }

    /**
     * 获取set方法
     * @param fieldname
     * @param cls
     * @return
     */
    public static method getsetter(string fieldname,class<?> cls){
        for (method method : cls.getmethods()) {
            if (method.getname().equalsignorecase("set".concat(fieldname)) && method.getparametertypes().length == 0){
                return  method;
            }
        }
        return null;
    }

    /**
     * 通过属性名获取field对象
     * @param fieldname
     * @param cls
     * @return
     */
    public static synchronized field getfieldbyname(string fieldname,class<?> cls){
        field[] fields =cls.getdeclaredfields();
        for (field field : fields){
            if (field.getname().equals(fieldname)){
                return field;
            }
        }

        if (cls.getsuperclass() != null){
            return getfieldbyname(fieldname,cls.getsuperclass());
        }

        return null;
    }

    /**
     * 通过对象.class获取所有fields,包括父类
     * @param cls
     * @return
     */
    public static list<field> listfields(class<?> cls){
        field[] fs = cls.getdeclaredfields();
        list<field> fields = new arraylist<>(arrays.aslist(fs));
        if (cls.getsuperclass() !=null){
            fields.addall(listfields(cls.getsuperclass()));
        }
        return fields;
    }

    public static  boolean fieldexist(string fieldname,class<?> cls){
        return getfieldbyname(fieldname, cls) !=null;
    }
}

到此这篇关于java基础之反射技术相关知识总结的文章就介绍到这了,更多相关java反射技术内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!