C++反射机制:可变参数模板实现C++反射

1. 概要

  本文描述一个通过C++可变参数模板实现C++反射机制的方法。该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能。Nebula框架在coding.net的仓库地址

  C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数。关于可变参数模板的原理和应用不是本文重点,不过通过本文中的例子也可充分了解可变参数模板是如何应用的。

  熟悉Java或C#的同学应该都知道反射机制,很多有名的框架都用到了反射这种特性,简单的理解就是只根据类的名字(字符串)创建类的实例。 C++并没有直接从语言上提供反射机制给我们用,不过无所不能的C++可以通过一些trick来实现反射。Bwar也是在开发Nebula框架的时候需要用到反射机制,在网上参考了一些资料结合自己对C++11可变参数模板的理解实现了C++反射。

<br/>

2. C++11之前的模拟反射机制实现

  Nebula框架是一个高性能事件驱动通用网络框架,框架本身无任何业务逻辑实现,却为快速实现业务提供了强大的功能、统一的接口。业务逻辑通过从Nebula的Actor类接口编译成so动态库,Nebula加载业务逻辑动态库实现各种功能Server,开发人员只需专注于业务逻辑代码编写,网络通信、定时器、数据序列化反序列化、采用何种通信协议等全部交由框架完成。

  开发人员编写的业务逻辑类从Nebula的基类派生,但各业务逻辑派生类对Nebula来说是完全未知的,Nebula需要加载这些动态库并创建动态库中的类实例就需要用到反射机制。第一版的Nebula及其前身Starship框架以C++03标准开发,未知类名、未知参数个数、未知参数类型、更未知实参的情况下,Bwar没想到一个有效的加载动态库并创建类实例的方式。为此,将所有业务逻辑入口类的构造函数都设计成无参构造函数。

  Bwar在2015年未找到比较好的实现,自己想了一种较为取巧的加载动态库并创建类实例的方法(这还不是反射机制,只是实现了可以或需要反射机制来实现的功能)。这个方法在Nebula的C++03版本中应用并实测通过,同时也是在一个稳定运行两年多的IM底层框架Starship中应用。下面给出这种实现方法的代码:

CmdHello.hpp:

#ifdef __cplusplus
extern "C" {
#endif
// @brief 创建函数声明
// @note 插件代码编译成so后存放到plugin目录,框架加载动态库后调用create()创建插件类实例。
neb::Cmd* create();
#ifdef __cplusplus
}
#endif

namespace im
{

class CmdHello: public neb::Cmd
{
public:
    CmdHello();
    virtual ~CmdHello();
    virtual bool AnyMessage();
};

} /* namespace im */

CmdHello.cpp:

#include "CmdHello.hpp"

#ifdef __cplusplus
extern "C" {
#endif
neb::Cmd* create()
{
    neb::Cmd* pCmd = new im::CmdHello();
    return(pCmd);
}
#ifdef __cplusplus
}
#endif

namespace im
{

CmdHello::CmdHello()
{
}

CmdHello::~CmdHello()
{
}

bool CmdHello::AnyMessage()
{
    std::cout << "CmdHello" << std::endl;
    return(true);
}

}

  实现的关键在于create()函数,虽然每个动态库都写了create()函数,但动态库加载时每个create()函数的地址是不一样的,通过不同地址调用到的函数也就是不一样的,所以可以创建不同的实例。下面给出动态库加载和调用create()函数,创建类实例的代码片段:

void* pHandle = NULL;
    pHandle = dlopen(strSoPath.c_str(), RTLD_NOW);
    char* dlsym_error = dlerror();
    if (dlsym_error)
    {
        LOG4_FATAL("cannot load dynamic lib %s!" , dlsym_error);
        if (pHandle != NULL)
        {
            dlclose(pHandle);
        }
        return(pSo);
    }
    CreateCmd* pCreateCmd = (CreateCmd*)dlsym(pHandle, strSymbol.c_str());
    dlsym_error = dlerror();
    if (dlsym_error)
    {
        LOG4_FATAL("dlsym error %s!" , dlsym_error);
        dlclose(pHandle);
        return(pSo);
    }
    Cmd* pCmd = pCreateCmd();

  对应这动态库加载代码片段的配置文件如下:

{"cmd":10001, "so_path":"plugins/CmdHello.so", "entrance_symbol":"create", "load":false, "version":1}

  这些代码实现达到了加载动态库并创建框架未知类实例的目的。不过没有反射机制那么灵活,用起来也稍显麻烦,开发人员写好业务逻辑类之后还需要实现一个对应的全局create()函数。

3. C++反射机制实现思考

  Bwar曾经用C++模板封装过一个基于pthread的通用线程类。下面是这个线程模板类具有代表性的一个函数实现,对设计C++反射机制实现有一定的启发:

``` c++
template <typename T>
void CThread<T>::StartRoutine(void para)
{
T
pT;
pT = (T*) para;
pT->Run();
}


&emsp;&emsp;与之相似,创建一个未知的类实例可以通过new T()的方式来实现,如果是带参数的构造函数,则可以new T(T1, T2)来实现。那么,通过类名创建类实例,建立"ClassName"与T的对应关系,或者建立"ClassName"与包含了new T()语句的函数的对应关系即可实现无参构造类的反射机制。考虑到new T(T1, T2)的参数个数和参数类型都未知,应用C++11的可变参数模板解决参数问题,即完成带参构造类的反射机制。

### 4. Nebula网络框架中的C++反射机制实现
&emsp;&emsp;研究C++反射机制实现最重要是[Nebula](https://github.com/Bwar/Nebula)网络框架中有极其重要的应用,而[Nebula](https://github.com/Bwar/Nebula)框架在实现并应用了反射机制之后代码量精简了10%左右,同时易用性也有了很大的提高,再考虑到应用反射机制后给基于[Nebula](https://github.com/Bwar/Nebula)的业务逻辑开发带来的好处,可以说反射机制是[Nebula](https://github.com/Bwar/Nebula)框架仅次于以C++14标准重写的重大提升。

&emsp;&emsp;Nebula的Actor为事件(消息)处理者,所有业务逻辑均抽象成事件和事件处理,反射机制正是应用在Actor的动态创建上。Actor分为Cmd、Module、Step、Session四种不同类型。业务逻辑代码均通过从这四种不同类型时间处理者派生子类来实现,专注于业务逻辑实现,而无须关注业务逻辑之外的内容。Cmd和Module都是消息处理入库,业务开发人员定义了什么样的Cmd和Module对框架而言是未知的,因此这些Cmd和Module都配置在配置文件里,Nebula通过配置文件中的Cmd和Module的名称(字符串)完成它们的实例创建。通过反射机制动态创建Actor的关键代码如下:

[Actor类](https://github.com/Bwar/Nebula/blob/master/src/actor/Actor.hpp):
``` C++
class Actor: public std::enable_shared_from_this<Actor>

Actor创建工厂(注意看代码注释):

``` C++
template<typename ...Targs>
class ActorFactory
{
public:
static ActorFactory* Instance()
{
if (nullptr == m_pActorFactory)
{
m_pActorFactory = new ActorFactory();
}
return(m_pActorFactory);
}

virtual ~ActorFactory(){};

// 将“实例创建方法(DynamicCreator的CreateObject方法)”注册到ActorFactory,注册的同时赋予这个方法一个名字“类名”,后续可以通过“类名”获得该类的“实例创建方法”。这个实例创建方法实质上是个函数指针,在C++11里std::function的可读性比函数指针更好,所以用了std::function。
bool Regist(const std::string& strTypeName, std::function<Actor*(Targs&&... args)> pFunc);

// 传入“类名”和参数创建类实例,方法内部通过“类名”从m_mapCreateFunction获得了对应的“实例创建方法(DynamicCreator的CreateObject方法)”完成实例创建操作。
Actor* Create(const std::string& strTypeName, Targs&&... args);

private:
ActorFactory(){};
static ActorFactory<Targs...> m_pActorFactory;
std::unordered_map<std::string, std::function<Actor
(Targs&&...)> > m_mapCreateFunction;
};

template<typename ...Targs>
ActorFactory<Targs...>* ActorFactory<Targs...>::m_pActorFactory = nullptr;

template<typename ...Targs>
bool ActorFactory<Targs...>::Regist(const std::string& strTypeName, std::function<Actor*(Targs&&... args)> pFunc)
{
if (nullptr == pFunc)
{
return (false);
}
bool bReg = m_mapCreateFunction.insert(
std::make_pair(strTypeName, pFunc)).second;
return (bReg);
}

template<typename ...Targs>
Actor* ActorFactory<Targs...>::Create(const std::string& strTypeName, Targs&&... args)
{
auto iter = m_mapCreateFunction.find(strTypeName);
if (iter == m_mapCreateFunction.end())
{
return (nullptr);
}
else
{
return (iter->second(std::forward<Targs>(args)...));
}
}


[动态创建类](https://github.com/Bwar/Nebula/blob/master/src/actor/DynamicCreator.hpp)(注意看代码注释):
``` C++
template<typename T, typename...Targs>
class DynamicCreator
{
public:
    struct Register
    {
        Register()
        {
            char* szDemangleName = nullptr;
            std::string strTypeName;
#ifdef __GUNC__
            szDemangleName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#else
            // 注意:这里不同编译器typeid(T).name()返回的字符串不一样,需要针对编译器写对应的实现
            //in this format?:     szDemangleName =  typeid(T).name();
            szDemangleName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#endif
            if (nullptr != szDemangleName)
            {
                strTypeName = szDemangleName;
                free(szDemangleName);
            }
            ActorFactory<Targs...>::Instance()->Regist(strTypeName, CreateObject);
        }
        inline void do_nothing()const { };
    };

    DynamicCreator()
    {
        m_oRegister.do_nothing();   // 这里的函数调用虽无实际内容,却是在调用动态创建函数前完成m_oRegister实例创建的关键
    }
    virtual ~DynamicCreator(){};

    // 动态创建实例的方法,所有Actor实例均通过此方法创建。这是个模板方法,实际上每个Actor的派生类都对应了自己的CreateObject方法。
    static T* CreateObject(Targs&&... args)
    {
        T* pT = nullptr;
        try
        {
            pT = new T(std::forward<Targs>(args)...);
        }
        catch(std::bad_alloc& e)
        {
            return(nullptr);
        }
        return(pT);
    }

private:
    static Register m_oRegister;
};

template<typename T, typename ...Targs>
typename DynamicCreator<T, Targs...>::Register DynamicCreator<T, Targs...>::m_oRegister;

  上面ActorFactory和DynamicCreator就是C++反射机制的全部实现。要完成实例的动态创建还需要类定义必须满足(模板)要求。下面看一个可以动态创建实例的CmdHello<a name="CmdHello"></a>类定义(注意看代码注释):

``` C++
// 类定义需要使用多重继承。
// 第一重继承neb::Cmd是CmdHello的实际基类(neb::Cmd为Actor的派生类,Actor是什么在本节开始的描述中有说明);
// 第二重继承为通过类名动态创建实例的需要,与template<typename T, typename...Targs> class DynamicCreator定义对应着看就很容易明白第一个模板参数(CmdHello)为待动态创建的类名,其他参数为该类的构造函数参数。
// 如果参数为某个类型的指针或引用,作为模板参数时应指定到类型。比如: 参数类型const std::string&只需在neb::DynamicCreator的模板参数里填std::string。
class CmdHello: public neb::Cmd, public neb::DynamicCreator<CmdHello, int32>
{
public:
CmdHello(int32 iCmd);
virtual ~CmdHello();

virtual bool Init();
virtual bool AnyMessage(
                std::shared_ptr<neb::SocketChannel> pChannel,
                const MsgHead& oMsgHead,
                const MsgBody& oMsgBody);

};


&emsp;&emsp;再看看上面的反射机制是[怎么调用](https://github.com/Bwar/Nebula/blob/master/src/labor/WorkerImpl.inl)的:

``` C++
template <typename ...Targs>
std::shared_ptr<Cmd> WorkerImpl::MakeSharedCmd(Actor* pCreator, const std::string& strCmdName, Targs... args)
{
    LOG4_TRACE("%s(CmdName \"%s\")", __FUNCTION__, strCmdName.c_str());
    Cmd* pCmd = dynamic_cast<Cmd*>(ActorFactory<Targs...>::Instance()->Create(strCmdName, std::forward<Targs>(args)...));
    if (nullptr == pCmd)
    {
        LOG4_ERROR("failed to make shared cmd \"%s\"", strCmdName.c_str());
        return(nullptr);
    }
    ...
}

  MakeSharedCmd()方法的调用:

``` C++
MakeSharedCmd(nullptr, oCmdConf["cmd"]i, iCmd);


&emsp;&emsp;至此通过C++可变参数模板实现C++反射机制实现已全部讲完,相信读到这里已经有了一定的理解,这是[Nebula](https://github.com/Bwar/Nebula)框架的核心功能之一,已有不少基于[Nebula的应用实践](https://github.com/Bwar/NebulaBootstrap),是可用于生产的C++反射实现。

&emsp;&emsp;这个C++反射机制的应用容易出错的地方是
* 类定义class CmdHello: public neb::Cmd, public neb::DynamicCreator<CmdHello, int32>中的模板参数一定要与构造函数中的参数类型严格匹配(不明白的请再阅读一遍[CmdHello类定义](#CmdHello))。
* 调用创建方法的地方传入的实参类型必须与形参类型严格匹配。不能有隐式的类型转换,比如类构造函数的形参类型为unsigned int,调用ActorFactory<Targs...>::Instance()->Create()时传入的实参为int或short或unsigned short或enum都会导致ActorFactory无法找到对应的“实例创建方法”,从而导致不能通过类名正常创建实例。

&emsp;&emsp;注意以上两点,基本就不会有什么问题了。

### 5. 一个可执行的例子
&emsp;&emsp;上面为了说明C++反射机制给出的代码全都来自[Nebula](https://github.com/Bwar/Nebula)框架。最后再提供一个可执行的例子加深理解。

DynamicCreate.cpp:
``` C++
#include <string>
#include <iostream>
#include <typeinfo>
#include <memory>
#include <unordered_map>
#include <cxxabi.h>

namespace neb
{

class Actor
{
public:
    Actor(){std::cout << "Actor construct" << std::endl;}
    virtual ~Actor(){};
    virtual void Say()
    {
        std::cout << "Actor" << std::endl;
    }
};

template<typename ...Targs>
class ActorFactory
{
public:
    //typedef Actor* (*ActorCreateFunction)();
    //std::function< Actor*(Targs...args) > pp;

    static ActorFactory* Instance()
    {
        std::cout << "static ActorFactory* Instance()" << std::endl;
        if (nullptr == m_pActorFactory)
        {
            m_pActorFactory = new ActorFactory();
        }
        return(m_pActorFactory);
    }

    virtual ~ActorFactory(){};

    //Lambda: static std::string ReadTypeName(const char * name)

    //bool Regist(const std::string& strTypeName, ActorCreateFunction pFunc)
    //bool Regist(const std::string& strTypeName, std::function<Actor*()> pFunc)
    bool Regist(const std::string& strTypeName, std::function<Actor*(Targs&&... args)> pFunc)
    {
        std::cout << "bool ActorFactory::Regist(const std::string& strTypeName, std::function<Actor*(Targs... args)> pFunc)" << std::endl;
        if (nullptr == pFunc)
        {
            return(false);
        }
        std::string strRealTypeName = strTypeName;
        //[&strTypeName, &strRealTypeName]{int iPos = strTypeName.rfind(‘ ‘); strRealTypeName = std::move(strTypeName.substr(iPos+1, strTypeName.length() - (iPos + 1)));};

        bool bReg = m_mapCreateFunction.insert(std::make_pair(strRealTypeName, pFunc)).second;
        std::cout << "m_mapCreateFunction.size() =" << m_mapCreateFunction.size() << std::endl;
        return(bReg);
    }

    Actor* Create(const std::string& strTypeName, Targs&&... args)
    {
        std::cout << "Actor* ActorFactory::Create(const std::string& strTypeName, Targs... args)" << std::endl;
        auto iter = m_mapCreateFunction.find(strTypeName);
        if (iter == m_mapCreateFunction.end())
        {
            return(nullptr);
        }
        else
        {
            //return(iter->second());
            return(iter->second(std::forward<Targs>(args)...));
        }
    }

private:
    ActorFactory(){std::cout << "ActorFactory construct" << std::endl;};
    static ActorFactory<Targs...>* m_pActorFactory;
    std::unordered_map<std::string, std::function<Actor*(Targs&&...)> > m_mapCreateFunction;
};

template<typename ...Targs>
ActorFactory<Targs...>* ActorFactory<Targs...>::m_pActorFactory = nullptr;

template<typename T, typename ...Targs>
class DynamicCreator
{
public:
    struct Register
    {
        Register()
        {
            std::cout << "DynamicCreator.Register construct" << std::endl;
            char* szDemangleName = nullptr;
            std::string strTypeName;
#ifdef __GUNC__
            szDemangleName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#else
            //in this format?:     szDemangleName =  typeid(T).name();
            szDemangleName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#endif
            if (nullptr != szDemangleName)
            {
                strTypeName = szDemangleName;
                free(szDemangleName);
            }

            ActorFactory<Targs...>::Instance()->Regist(strTypeName, CreateObject);
        }
        inline void do_nothing()const { };
    };
    DynamicCreator()
    {
        std::cout << "DynamicCreator construct" << std::endl;
        m_oRegister.do_nothing();
    }
    virtual ~DynamicCreator(){m_oRegister.do_nothing();};

    static T* CreateObject(Targs&&... args)
    {
        std::cout << "static Actor* DynamicCreator::CreateObject(Targs... args)" << std::endl;
        return new T(std::forward<Targs>(args)...);
    }

    virtual void Say()
    {
        std::cout << "DynamicCreator say" << std::endl;
    }
    static Register m_oRegister;
};

template<typename T, typename ...Targs>
typename DynamicCreator<T, Targs...>::Register DynamicCreator<T, Targs...>::m_oRegister;

class Cmd: public Actor, public DynamicCreator<Cmd>
{
public:
    Cmd(){std::cout << "Create Cmd " << std::endl;}
    virtual void Say()
    {
        std::cout << "I am Cmd" << std::endl;
    }
};

class Step: public Actor, DynamicCreator<Step, std::string, int>
{
public:
    Step(const std::string& strType, int iSeq){std::cout << "Create Step " << strType << " with seq " << iSeq << std::endl;}
    virtual void Say()
    {
        std::cout << "I am Step" << std::endl;
    }
};

class Worker
{
public:
    template<typename ...Targs>
    Actor* CreateActor(const std::string& strTypeName, Targs&&... args)
    {
        Actor* p = ActorFactory<Targs...>::Instance()->Create(strTypeName, std::forward<Targs>(args)...);
        return(p);
    }
};

}

int main()
{
    //Actor* p1 = ActorFactory<std::string, int>::Instance()->Create(std::string("Cmd"), std::string("neb::Cmd"), 1001);
    //Actor* p3 = ActorFactory<>::Instance()->Create(std::string("Cmd"));
    neb::Worker W;
    neb::Actor* p1 = W.CreateActor(std::string("neb::Cmd"));
    p1->Say();
    //std::cout << abi::__cxa_demangle(typeid(Worker).name(), nullptr, nullptr, nullptr) << std::endl;
    std::cout << "----------------------------------------------------------------------" << std::endl;
    neb::Actor* p2 = W.CreateActor(std::string("neb::Step"), std::string("neb::Step"), 1002);
    p2->Say();
    return(0);
}

  Nebula框架是用C++14标准写的,在Makefile中有预编译选项,可以用C++11标准编译,但未完全支持C++11全部标准的编译器可能无法编译成功。实测g++ 4.8.5不支持可变参数模板,建议采用gcc 5.0以后的编译器,最好用gcc 6,Nebula用的是gcc6.4。

  这里给出的例子DynamicCreate.cpp可以这样编译:

 g++ -std=c++11 DynamicCreate.cpp -o DynamicCreate

  程序执行结果如下:

DynamicCreator.Register construct
static ActorFactory* Instance()
ActorFactory construct
bool ActorFactory::Regist(const std::string& strTypeName, std::function<Actor*(Targs... args)> pFunc)
m_mapCreateFunction.size() =1
DynamicCreator.Register construct
static ActorFactory* Instance()
ActorFactory construct
bool ActorFactory::Regist(const std::string& strTypeName, std::function<Actor*(Targs... args)> pFunc)
m_mapCreateFunction.size() =1
static ActorFactory* Instance()
Actor* ActorFactory::Create(const std::string& strTypeName, Targs... args)
static Actor* DynamicCreator::CreateObject(Targs... args)
Actor construct
DynamicCreator construct
Create Cmd
I am Cmd
----------------------------------------------------------------------
static ActorFactory* Instance()
Actor* ActorFactory::Create(const std::string& strTypeName, Targs... args)
static Actor* DynamicCreator::CreateObject(Targs... args)
Actor construct
DynamicCreator construct
Create Step neb::Step with seq 1002
I am Step

  完毕,周末花了6个小时才写完,找了个合适的时间发布出来。如果觉得这篇文章对你有用,如果觉得Nebula还可以,麻烦到GitHub上给个star,感谢。 Nebula不仅是一个框架,还提供了一系列基于这个框架的应用,目标是打造一个高性能分布式服务集群解决方案。

<br/>

参考资料:

原文地址:http://blog.51cto.com/5662165/2142574

时间: 2024-10-13 04:27:35

C++反射机制:可变参数模板实现C++反射的相关文章

java反射机制(一)—— 利用反射机制实例化对象

一.Java有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载.探知.使用编译期间完全未知的classes.换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体.或对其fields设值.或唤起其methods.(度娘文库是这么说的) 二.这篇文章主要介绍一下通过反射机制去实例化一个类的对象,然后调用其方法.本文主要介绍两种方式,第一种就是通过构造函数来实例化,第二种就是通过Cl

Java反射机制

Java的反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 反射的作用 1 可以反编译将class文件编译成java文件 2 可以通过反射机制访问Java对象的属性,方法,构造方法等 反射机制使用步骤 1 得到要调用类的class 2 通过得到的c

使用反射机制调用属性和私有成员与代理模式的介绍

使用反射机制调用属性: 通过反射机制可以获得类的属性,获得到的属性同样的可以进行赋值.得值操作,调用getField方法并传递属性的名称可以获得[学Java,到凯哥学堂kaige123.com]指定的属性,调用getFields方法则可以获得全部属性,但是这种方式不能获得私有属性: 代码示例: Student类示例: 运行结果: 从运行结果可以看出只拿出了公开的属性,私有的属性拿不到. 使用反射机制调用私有成员: 1.调用私有属性 在反射机制里调用私有属性需要通过getDeclaredField

反射机制

反射机制: 反射机制是能够帮助我们把代码变得更加灵活,可扩展性更高,俗称"软编程.软写法".例如:有一个文件里面有一些值,想要把这些值赋值到一个Student类的属性中,按照以前所学到的知识点,只能是通过文件流将文件里的值读取出来,然后再通过set方法将这些值都赋给Student类的属性.但是,这种方式是将代码写死了,在这之后会有一个问题就是如果文件里的内容发生变动,或者要把这个Student类更换成Dog类的话,就要重新修改代码.程序写好了部署到服务器上运行了,总不能时不时就打开来修

java的反射机制

一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动,说不定会请各位吃饭哦! 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2.反射

java反射机制之基础

一.什么是反射机制 简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制 有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行代码,Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成驱动对象实例,并不知道它的具体含义.听了反射机制这节课后,才知道,原来这

java 反射机制:运行时的类信息(为框架服务的Bug存在)

反射机制:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 换一种引出反射的说法是:当通过反射与一个未知的类型的对象打交道是,JVM只是简单地检查这个类,看它是属于哪个特定的类(就想RTTI那样).在用它做其他事情之前必须先加载那个类的Class对象.因此,那个类的.class文件对于JVM来说必须是可获取的:那么在本地机器上,要么通过网络获得

java的泛型与反射机制

什么是泛型? 泛型,即"参数化类型".顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参). 为什么要使用泛型? 先看如下代码: public class GenericTest { public static void main(String[] args) { List list = new ArrayList(); list.add("qqyumidi"

moon 反射机制---java.lang.reflect包

java反射机制:在运行状态中,对于一个已经加载到JVM的java对象/类 在程序中实现访问.检查.修改.描述java对象本身的信息(构造方法.方法.成员变量.类本身的信息) 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. C++,Java,C#不是动态语言.但是JAVA有着一个非常突出的动态相关机制:Reflection, 反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接. 二,反射机制的作用: