Step By Step(Java 常用对象篇<二>) (四)

2014-11-24 03:21:36 · 作者: · 浏览: 3
fineClass方法并返回预定义类的Class对象。

1 //FileClassLoader为自定义的ClassLoader

2 public class FileClassLoader extends ClassLoader {

3 public static final String drive = "d:/";

4 public static final String fileType = ".class";

5 public FileClassLoader() {

6 super();

7 }

8 public FileClassLoader(ClassLoader arg0) {

9 super(arg0);

10 }

11 public Class< > findClass(String name) {

12 byte[] data = loadClassData(name);

13 return defineClass(name, data, 0, data.length);

14 }

15 public byte[] loadClassData(String name) {

16 FileInputStream fis = null;

17 byte[] data = null;

18 try {

19 fis = new FileInputStream(new File(drive + name + fileType));

20 ByteArrayOutputStream baos = new ByteArrayOutputStream();

21 int ch = 0;

22 //可以在这里完成读入后解密再回写的byte数组中的操作。

23 while ((ch = fis.read()) != -1)

24 baos.write(ch);

25 data = baos.toByteArray();

26 } catch (IOException e) {

27 e.printStackTrace();

28 }

29 return data;

30 }

31 }

32 //该测试类为将被FileClassLoader加载的class

33 public class MyApp {

34 private static int ii = 0;

35 static {

36 ii = 10;

37 System.out.println("Static block is initialized.");

38 }

39

40 public void print() {

41 System.out.println("ii = " + ii);

42 System.out.println("This is MyApp.print");

43 }

44 }

45 //以下代码为测试自定义ClassLoader调用的代码

46 public static void main(String[] args) throws Exception {

47 //如果将MyApp.class文件同时放到D:/根目录和应用程序当前的bin目录下时,

48 //会发现MyApp的类加载器不在是FileClassLoader,而是sun.misc.Launcher$AppClassLoader,

49 //因为AppClassLoader作为FileClassLoader的parent已经加载了该class,

50 //因此FileClassLoader将不会再重新加载该class。

51 FileClassLoader loader = new FileClassLoader();

52 Class< > objClass = loader.loadClass("MyApp");

53 System.out.println("Begin to getMethod");

54 Method m = objClass.getMethod("print");

55 System.out.println("Begin to newInstance.");

56 Object obj = objClass.newInstance();

57 System.out.println("Begin to invoke.");

58 m.invoke(obj);

59 System.out.println(objClass.getName());

60 System.out.println(objClass.getClassLoader());

61 }

62 /* 输出结果如下:

63 Begin to getMethod

64 Begin to newInstance.

65 Static block is initialized.

66 Begin to invoke.

67 ii = 10

68 This is MyApp.print

69 MyApp

70 FileClassLoader@1d7ad1c

71 */

复制代码

在介绍关于ClassLoader的最后,我们来讨论一下Class.forName("className")和loader.loadClass("className")两者之间的区别。

Class.forName()包含两个Overload的方法,我们经常使用的Class.forName(name)方法,在其实现的内部将会调用另一个Class.forName(name,initialize,loader)方法,其等同于Class.forName(name,true,CallClass.class.getClassLoader())的调用。这里的第二个参数表示装载类的时候是否初始化该类,即是否调用类的静态块的语句及初始化静态成员变量。而Class c = ClassLoader.loadClass(name)没有指定是否初始化的选项。因此在调用该方法时,被调用类的静态块代码不会被执行,静态变量也不会