java 动态扩展_java 动态扩展方式

java 除了在运行时连接类型之外,还可以在运行时动态决定连接哪一种类型。java的体系结构允许动态扩展java程序,过程包括运行时决定所使用的类型,装载它们,使用它们。

一、动态扩展的方法

通过传递类型的名称,使用java.lang.class的forName()方法。

通过用户自定义的类装载器的loadClass()方法,用户自定义的类装载器可以从java.class.ClassLoader的任何子类创建。

二、动态扩展的例子:

浏览器启动的时候,不知道将要从网络上装载的class的文件,当遇到applet的网页时才知道每个applet所需的类和接口的名字。

三、程序:

1、使用java.lang.class的forName()方法:

public class TestClass {

public void hello() {

System.out.println("Hello,World!");

}

}

public class TestForName {

/**

*

* @param args

*/

public static void main(String args[]) {

if (args.length == 0) {

System.out.println("please input the class name!");

return;

}

for (int i = 0; i < args.length; i++) {

try {

Class> c = Class.forName(args[i]);

Object obj = c.newInstance();

TestClass tc = (TestClass) obj;

tc.hello();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

}

程序解析:

forName()接受的字符串参数是类型的全限定名称,如果成功装载了类型,或者之前已经被成功装载过,会返回代表类型的Class的实例,如果不成功,将会抛出ClassNotFoundException异常。

forName()试图确认所需的类型被装载到当前命名空间中,这个当前的命名空间就是类型所属的定义类装载器的命名空间。如果没有明确地在命令行或者环境变量中指定一个类的路径,系统类装载器会在当前目录中寻找所需的类型。

2、使用自定义的类装载器的loadClass()方法

方法:

程序:

import java.io.BufferedInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

/**

* @author hansen

*

*/

public class TestClassLoader extends ClassLoader {

private String basePath;

/**

* constructor

*

* @param basePath

*/

public TestClassLoader(String basePath) {

this.basePath = basePath;

}

/**

* constructor

*

* @param parent

* @param basePath

*/

public TestClassLoader(ClassLoader parent, String basePath) {

super(parent);

this.basePath = basePath;

}

/*

* (non-Javadoc)

*

* @see java.lang.ClassLoader#findClass(java.lang.String)

*/

@Override

protected Class> findClass(String className)

throws ClassNotFoundException {

byte[] classData = getTypeFromBasePath(className);

if (null == classData) {

throw new ClassNotFoundException();

}

return defineClass(className, classData, 0, classData.length);

}

/**

* get the class type from the base path

*

* @param typeName

* @return

*/

private byte[] getTypeFromBasePath(String typeName) {

FileInputStream in = null;

String fileName = basePath + File.separatorChar

+ typeName.replace('.', File.separatorChar) + ".class";

try {

in = new FileInputStream(fileName);

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

BufferedInputStream input = new BufferedInputStream(in);

ByteArrayOutputStream out = new ByteArrayOutputStream();

try {

int c = input.read();

while (c != -1) {

out.write(c);

c = input.read();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return out.toByteArray();

}

}

解析:

findClass的工作方式:

1、接受需要装载的类型的全限定名称作为唯一的参数。首先试图查找或者生生成一个字节数组,内容是java class文件格式,文件格式定义了所需要装载的类型。

2、如果findClass()无法确定或者生成字节数组,会抛出ClassNotFoundException()异常并中止。否则findClass()调用defineClass(),把所需的类型名称、字节数组和一个可选的指定了这个类型所属的受保护域的ProtectionDomain对象作为参数。

3、如果defineClass()返回了一个代表这个类型的Class实例,findClass()简单地吧同一个Class实例返回给它的调用者。否则,defineClass()抛出某些异常并中止findClass()也抛出同样的异常并中止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值