但是如果实现类需要通过静态方法来进行初始化的时候,动态加载的过程就会复杂一些。同样的以数据库连接池为例,通常连接池的构造函数都会被定义为私有的,而通过自定义的getInstance()静态方法来得到唯一实例。这种情况下简单的通过Class.forName().getInstance()就无法正确构造实例。
幸好Java所提供的反射机制(Reflection)为我们提供了完整了探悉类内部结构的方法。通过反射机制,我们能够完成基本上所有的运行时决定的动作(虽然这一实现要比其他动态语言,比如PHP,的eval()的使用要复杂的多)。
下面通过实际的例子说明如何在运行时动态访问类的静态方法。
------------------------------------------------------- */ import java.lang.reflect.*; public class myTestClass{ private static Object pLock = new Object(); private static myTestClass p_instance = null; private String s_configName = ""; private boolean b_isFromResource = true; public static Object getInstance(String sConfigName, Boolean bIsFromResource){ synchronized(pLock){ if(null == p_instance){ p_instance =new myTestClass(sConfigName,bIsFromResource); } } return p_instance; } private myTestClass(String sConfigName,Boolean bIsFromResource){ s_configName = sConfigName; b_isFromResource = bIsFromResource.booleanValue(); } public void echoInfo(){ System.out.println("current arguments : configName=["+ s_configName+"],isFromResource=["+b_isFromResource+"]"); } public static void main(String[] args) throws Exception{ // 设置方法的传入参数的类型. Class[] parameterTypes = new Class[]{ java.lang.String.class, java.lang.Boolean.class }; Method mGetInstance = null; String className = "myTestClass"; Class curTestClass = Class.forName(className); try{ mGetInstance = curTestClass.getMethod("getInstance",parameterTypes); } catch(NoSuchMethodException e){ e.printStackTrace(); mGetInstance = null; } if(mGetInstance != null){ myTestClass pObj = (myTestClass) mGetInstance.invoke(null,new Object[]{ "src/myconfig.properties", Boolean.FALSE } ); pObj.echoInfo(); } else{ throw new Exception("myTest Init Failed from class" + className + System.getProperty("line.seperator","\n") + "method getInstance(String, Boolean) exists."); } } } |