• 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...

    动态加载 。。。。

    如果没有不带参数的构造函数,则不能通过c1.newInstance() 构造对象,需要先获取构造函数,再构造对象

           Class c = Class.forName("com.my.app.Book");
                
                Constructor con = c.getConstructor(String.class);
                
                Book book = (Book) con.newInstance("语文");
            
                System.out.println(book);

     4.获取方法,运行方法:

    package com.my.app;
    
    public class Book {
        
        private String name ="金1瓶1梅";
        
        
        
        public Book() {
            super();
        }
    
        public Book(String name) {
            super();
            this.name = name;
        }
    
        public void  outDate(){
            System.out.println("1111111 ");
        }
        
        public void  outDate(String string){
            System.out.println("1111111 " +string);
        }
        
        
        public void  outDate(String string,int num){
            System.out.println("1111111 " +string +" " +num);
        }
    
    }
    
                Class c = Class.forName("com.my.app.Book");
                Book book = (Book) c.newInstance();
                book.outDate();
                Method[] methods = c.getMethods();
            
                Method method = c.getMethod("outDate", String.class,int.class);
                
                method.invoke(book, "6465465",55);       

            Method method = c.getMethod("outDate", String.class);

            method.invoke(book, "6465465");

     获取变量

    Class c = Class.forName("com.my.app.Book");
                    Book book = (Book) c.newInstance();
                    
                    Field field1 = c.getField("price");//根据变量名,返回一个具体的具有public属性的成员变量
                    
                    Field field2 = c.getDeclaredField("price");//根据变量名,返回一个成员变量(不分public和非public属性)
                    System.out.println(field1.getDouble(book));
                    
                    System.out.println(field2.getName());//获取变量名
                    System.out.println(field2.getType());//获取变量类型
                    System.out.println(field2.get(book));//获取变量值
                    System.out.println(field2.getDouble(book));//获取变量值
                    
                    //获取私有字段 模拟get set方法
                    Field nameField = c.getDeclaredField("name");
                    //取消访问私有字段的合法性检查
                    nameField.setAccessible(true);
                    
                    System.out.println(nameField.get(book));
                    
                    nameField.set(book, "BBBB");
                    System.out.println(book);
  • 相关阅读:
    springMVC 返回json 忽略类中属性的注解
    MySQL中函数CONCAT及GROUP_CONCAT
    ArrayList转成HashMap再转成LinkedHashMap 自己的解决方案
    easyui datebox 设置不可编辑
    js或jquery如何获取父级、子级、兄弟元素(包括祖级、孙级等)
    关于js中空值比较和传值的问题
    Tomcat报错:Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
    JQuery 阻止js事件冒泡 阻止浏览器默认操作
    visualstudio2017 +EF+Mysql生成实体数据模型闪退
    MVC错误:查询的结果不能枚举多次
  • 原文地址:https://www.cnblogs.com/lukelook/p/10851111.html
Copyright © 2020-2023  润新知