java 反射 加载指定目录下的Class文件

1    最近由于公司android 客服端的兄弟想做 动态扩展android应用,而不通过 重新发布版本来来实现,所以就考虑到用java的反射 加载指定的类

 

     A 一般加载类的  Class.froName的方法,这个方法是加载 已经集成或者导入到 项目下的jar 下面的类

 

          如是 找到Class类,发现只有 Class.forName的方法

 

     如是去找ClassLoader 发现 一个defineClass   的方法可以 接受字节数组,来生产Class对象,但是

 

  在编码工具中Eclipse 去实例这个类,在调用这个方法是,竟然发现竟然说这个方法不存在,开始我以为是文档的问题,

 

后面一想 ,java 中有许多方法是提供给jvm虚拟机用的,编码工具对其进行的过滤,后面同事收到一篇同样需求的代码,

 

 

一看才想明白,既然不能在外部调用,如果继承这个类,再重写这个方法,就可以实现这样的需求,额,有时候看样子还是

 

想的不够

 

好了,看实现类代码

public class ClassLoaderExpand extends ClassLoader {

	/**
	 * name class 类的文件名
	 */
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] datas = loadClassData(name);  
		return defineClass(name, datas, 0, datas.length);  
	}

	// 指定文件目录
	private String location;
	
	 public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}


	protected byte[] loadClassData(String name)  
	    {  
	    FileInputStream fis = null;  
	     byte[] datas = null;  
	    try  
	    {  
	       fis = new FileInputStream(location+name+".class");  
	       ByteArrayOutputStream bos = new ByteArrayOutputStream();  
	        int b;  
	        while( (b=fis.read())!=-1 )  
	         {  
	         bos.write(b);  
	         }  
	        datas = bos.toByteArray();  
	        bos.close();  
	     }catch(Exception e)  
	     {  
	         e.printStackTrace();  
	     }  
	     finally  
	     {  
	         if(fis != null)  
	        try  
	         {  
	             fis.close();  
	        } catch (IOException e)  
	         {  
	             e.printStackTrace();  
	         }  
	     }  
	     return datas;  
	
	  }  
}

 

再看调用方式

//实例扩展类
		ClassLoaderExpand clod=new ClassLoaderExpand();
		
		//指定java class 文件目录
		clod.setLocation("E:/service/");
		
		try {
			//调用 通过字节流生产java类
	    Class cl=clod.findClass("Test");
	    
	    //这里是调用带参数的方法,参数是数组对象
		Method method	=cl.getMethod("test2",new Class[]{String [].class});
		//如果这里 调用的是 实例方法 和以上的一样,只是后面调用Method的invoke不一样
		
		
		System.out.println(method.getName());
		
		
		method.invoke(cl, new Object[]{new String []{}});
//这里的cl 是 生产的类,为什么这里没有  cl.newInstance() ,因为调用的test2 是静态方法,如果不是静态方法,需要用一下的
//		method.invoke(cl.newInstance(), new Object[]{new String []{}});
		
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

 

 

好了再看 Test 类中有哪些方法

public  void test1() {

		System.out.println("-----------1---------");
		
		
		System.out.println("asdfasdfasdfasd");
	}

	public static void test2(String[] args) {

		System.out.println("----------2----------");
		
		
		System.out.println("asdfasdfasdfasd");
	}

 

 

 

 

你可能感兴趣的:(Class文件)