Class.forName与动态加载
Posted GaJa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Class.forName与动态加载相关的知识,希望对你有一定的参考价值。
可以通过Class.forName("类的全类名")方法创建一个类的类类型。不仅如此,这个方法还表示了动态加载类。
动态加载类与静态加载类的区分:
- 编译时刻加载的类称为静态加载类。
- 运行时刻加载的类称为动态加载类。
静态加载的不足:在编译时就会把所有类都加载,不论是否使用
Office.java类
1 class Office{
2 public static void main(String args[]){
3 if("Word".equals(args[0])){
4 Word word=new Word();
5 word.start();
6 }
7 if("Excel".equals(args[0])){
8 Excel excel=new Excel();
9 excel.start();
10 }
11 }
12 }
思考:这个程序是否能够通过编译?
Office.java:4: 错误: 找不到符号 Word word=new Word(); ^ 符号: 类 Word 位置: 类 Office Office.java:4: 错误: 找不到符号 Word word=new Word(); ^ 符号: 类 Word 位置: 类 Office Office.java:8: 错误: 找不到符号 Excel excel=new Excel(); ^ 符号: 类 Excel 位置: 类 Office Office.java:8: 错误: 找不到符号 Excel excel=new Excel(); ^ 符号: 类 Excel 位置: 类 Office 4 个错误
思考:毫无疑问肯定是编译失败的,因为Word、Excel类还没有定义,当然也不存在两个start()方法。正因为如此编译失败也就理所当然了,但是如果多考虑一点:Word用吗?Excel用吗?也许这两个类与两个方法都用不到,既然都不用,可是编译却无法通过。
Word.java:编写Word类和start方法
1 class Word {
2 public void start(){
3 System.out.println("Word...starts..");
4 }
5 }
继续编译这个程序:现在只报了两个关于Excel的错误。
F:\xj>javac Word.java F:\xj>javac Office.java Office.java:8: 错误: 找不到符号 Excel excel=new Excel(); ^ 符号: 类 Excel 位置: 类 Office Office.java:8: 错误: 找不到符号 Excel excel=new Excel(); ^ 符号: 类 Excel 位置: 类 Office 2 个错误
思考:此刻再来思考和上面一样的问题,如果只需要Word,不需要Excel,但是这个程序也依然运行不了。因为程序做的是静态加载。即:new方式创建对象的都是静态加载类。
使用静态加载导致了不管这些类是否使用,在编译的时候就必须加载所有可能使用到的类。
然而在实际中,希望Word存在,Word就可以用;当用Excel的时候java编译器你再提醒我Excel有问题。就例如我们程序中有100个程序,但是只要是一个有了问题,其他的都用不了。其实这并不是我们想要看到的。这就是编译时加载导致的。所以希望利用运行时动态加载来解决该问题。
动态加载
通过new方法来创建对象都是静态加载,但是通过forName()方法去可以进行动态加载。
OfficeBetter.java:这里采用动态加载
1 class OfficeBetter{
2 public static void main(String args[]){
3 try{
4 //动态加载类在运行时刻。编译的时候并不会报错,他才不会管你是哪个类呢。
5 Class classWord=Class.forName(args[0]);
6 }catch(Exception e){
7 e.printStackTrace();
8 }
9 }
10 }
问题:接下来创建对象又有了问题了,如果这里面使用Word word=(Word)classWord.newInstance(),此刻如果传入的是Excel就出现问题了;如果往Excel做强制类型转换,那么如果传入Word同样会出现问题。
思路:所以这里面要提升一下思想,给Word与Excel制定一个标准,然后让Word与Excel实现这个标准OfficeAble。完整代码如下:
OfficeBetter.java:
1 class OfficeBetter{ 2 public static void main(String args[]){ 3 try{ 4 Class class01=Class.forName(args[0]); 5 OfficeAble oa=(OfficeAble)class01.newInstance(); 6 oa.start(); 7 }catch(Exception e){ 8 e.printStackTrace(); 9 } 10 } 11 12 }
OfficeAble.java:接口
1 interface OfficeAble{
2 public void start();
3 }
Word.java:
1 class Word implements OfficeAble{
2 public void start(){
3 System.out.println("Word...starts..");
4 }
5 }
此刻编译都是完全可以通过, 然后我们分别输入Excel与word
F:\xj>java OfficeBetter Excel
java.lang.ClassNotFoundException: Excel
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at OfficeBetter.main(OfficeBetter.java:5)
F:\xj>java OfficeBetter Word
发现:当输入Excel的时候才会发生错误,但是当输入Word的时候完全可以使用。
和之前的相比,不同的是,这里面编译的时候没有任何问题。word也可以正常使用。只有在输入Excel,开始运行Excel的时候才会报错——notFoundException。 这正是我们需要的动态加载:在编译的时候不去理会,在使用的时候再去判断。
接下来就可以创建对象了:
通过类类型创建该类的对象。
运行结果:
F:\xj>javac OfficeBetter.java
F:\xj>java OfficeBetter Word
Word...starts..
当然类似Word类,也可以建一个Excel类:
class Excel implements OfficeAble{ public void start(){ System.out.println("Excel...starts.."); } } F:\xj>javac Excel.java F:\xj>java OfficeBetter Excel Excel...starts...
这里面OfficeBetter这个类不用再编译,直接运行就可以了
功能性的类一般使用动态加载,而不是静态加载
END.
以上是关于Class.forName与动态加载的主要内容,如果未能解决你的问题,请参考以下文章
Java - 如何用 Class.forName 加载外部 Jar 里的类文件?