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();
}
}java replace方法
}
}
程序解析:
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
+ place('.', 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 = ad();
while (c != -1) {
out.write(c);
c = ad();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ByteArray();
}
}
解析:
findClass的⼯作⽅式:
1、接受需要装载的类型的全限定名称作为唯⼀的参数。⾸先试图查或者⽣⽣成⼀个字节数组,内容是java class⽂件格式,⽂件格式定义了所需要装载的类型。
2、如果findClass()⽆法确定或者⽣成字节数组,会抛出ClassNotFoundException()异常并中⽌。否则findClass()调⽤defineClass(),把所需的类型名称、字节数组和⼀个可选的指定了这个类型所属的受保护域的ProtectionDomain对象作为参数。
3、如果defineClass()返回了⼀个代表这个类型的Class实例,findClass()简单地吧同⼀个Class实例返回给它的调⽤者。否
则,defineClass()抛出某些异常并中⽌findClass()也抛出同样的异常并中⽌。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论