Java动态加载类

Posted lukelook

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java动态加载类相关的知识,希望对你有一定的参考价值。

详见:https://blog.csdn.net/zai_xia/article/details/80026325

扩展:java反射机制与动态加载类 https://www.cnblogs.com/wzk-0000/p/9322866.html

在讲解动态加载类之前呢,我们先弄清楚为什么要动态加载类,静态加载不行吗?我们可以看下面的实例:

我在文件夹里写了Office.java 类和 Word.java类,如下:

技术图片

Office.java

class Office{
    public static void main(String[] args){
        if(args[0].equals("Word")){
            Word w = new Word();
            w.start();
        }
        if(args[0].equals("Excel")){
            Excel e = new Excel();
            e.start();
        }
    }

Word.java

class Word{
    public void start(){
        System.out.println("Word Start");
    }

编译会报错,这当然没问题,因为确实没有写Excel.java类。

但是这个Excel类我们一定会用到吗?如果这个Excel类需要很久才能写出来,在此我们也不能使用其他功能吗?后面如果一个类出问题了,这个系统是不是就瘫痪了?

所以这就体现出动态加载类的好处了,动态加载类是按需加载的,你需要什么类,就加载什么类,一个类的状态,不会影响到另一个类的使用。

所以我们可以将Office类改造如下:

class Office{
    public static void main(String[] args){
        try{
            Class c = Class.forName(args[0]);
            Word w = (Word)c.newInstance();
            w.start();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        
    }

虽然我们还是没有写Excel类,但此时我们再编译Office.java文件,编译通过;

成功按照我们预想的结果运行,这样Word类就可以单独运行。

但是这样还是不够规范,因为现在只能加载Word类类型的类文件,为了使程序有更好的扩展性,我们添加一个接口,只有让所有的功能类实现该接口即可。完善如下:

OfficeAble.java

interface OfficeAble{
    public void start();
}

Office.java

class Office{
    public static void main(String[] args){
        try{
            Class c = Class.forName(args[0]);
            OfficeAble oa = (OfficeAble)c.newInstance();
            oa.start();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        
    }

Word.java

class Word implements OfficeAble{
    public void start(){
        System.out.println("Word Start");
    }
}

这样改造之后,我后面要添加一个Excel类,乃至添加其他的类,只需要实现OfficeAble接口就可以了,不需要改动Office这个类和其他的功能类,扩展性很强,这就是动态加载的优势。

 

扩展:java的反射机制与动态加载

 

什么是java反射机制?

 

1、当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射。
IT行业里这么说,没有反射也就没有框架,现有的框架都是以反射为基础。在实际项目开发中,用的最多的是框架,填的最多的是类,反射这一概念就是将框架和类揉在一起的调和剂。所以,反射才是接触项目开发的敲门砖。

 

2、java中的new方法是静态加载,因为new方法是在编译阶段就会检查,而不是在运行阶段。反射是可以在运行时创建对象,调用对象的方法、变量等。

 

3、Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

 

例如:

package service.impl;

public class Test {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        F f = new F();
        // 第一种表达方式
        Class c1 = F.class;// 这种表达方式同时也告诉了我们任何一个类都有一个隐含的静态成员变量class
        // 第二种表达方式
        Class c2 = f.getClass();// 这种表达方式在已知了该类的对象的情况下通过getClass方法获取
        // 第三种表达方式
        Class c3 = Class.forName("service.impl.F");// 类的全称

        System.out.println(c1.getName());
        System.out.println(c2.getName());
        System.out.println(c3.getName());
        F temp = (F) c1.newInstance();//这里可以是c1/c2/c3
        System.out.println(temp.f);
        temp.save();
    }
}

class F {
    public String f = "test";

    public void save() {
        System.out.println("save...");
    }
}

运行结果

service.impl.F
service.impl.F
service.impl.F
test
save...

动态加载 。。。。

 

以上是关于Java动态加载类的主要内容,如果未能解决你的问题,请参考以下文章

[JAVA冷知识]动态加载不适合数组类?那如何动态加载一个数组类?

在android中动态创建选项卡并使用传入的参数加载片段

[JAVA冷知识]动态加载不适合数组类?那如何动态加载一个数组类?

solr分布式索引实战分片配置读取:工具类configUtil.java,读取配置代码片段,配置实例

Android 逆向类加载器 ClassLoader ( 类加载器源码简介 | BaseDexClassLoader | DexClassLoader | PathClassLoader )(代码片段

Java:动态加载同一类的多个版本