Java类加载和反射

Java类加载和反射,java,classloader,Java,Classloader,我在运行时使用urlclassloader加载jar文件。 Jar文件和类正在成功加载。 我有一个类,它有一个返回对象X的方法。 使用对象X,我必须调用X上的Setter方法 如何调用X上的setter方法 我通过调用方法返回了对象X X = my.invoke(inst, obj); 我是否需要通过调用X类上的newInstance()方法再次创建实例 要调用对象X的方法,是否每次都必须调用method.invoke()? 假设X对象有5个方法,找到该方法并使用method.invoke.

我在运行时使用urlclassloader加载jar文件。 Jar文件和类正在成功加载。 我有一个类,它有一个返回对象X的方法。 使用对象X,我必须调用X上的Setter方法

如何调用X上的setter方法

我通过调用方法返回了对象X

X = my.invoke(inst, obj);
  • 我是否需要通过调用X类上的
    newInstance()
    方法再次创建实例
  • 要调用对象X的方法,是否每次都必须调用
    method.invoke()
    ? 假设X对象有5个方法,找到该方法并使用
    method.invoke.
  • 你的建议会很有帮助

       File f1 = new File("/home/egkadas/CR364/lib/xxx.jar");
       URL urls [] = new URL[1];
       urls[0] = f1.toURL(); 
        
       URLClassLoader urlClass = URLClassLoader.newInstance(urls);
       Class c1 = urlClass.loadClass("com.xxxx.example.poc.Container");
       Container  inst = (Container)c1.newInstance();
        
       if(inst == null){
            System.out.println("Object is null");
       }else{
         Method my = c1.getMethod("getAttribute",null);
          Object[] obj = new Object[0];
     com.XXXXX.example.poc.Container.Attributes att =(com.XXXXX.example.poc.Container.Attributes)my.invoke(inst, obj);
          System.out.println(att);
    
       
    
    jar中的代码:

    public class Container {
        
        public String id;
        
        public Container(){
            
        }
        
        public Container(String id){
            this.id=id;
        }
    
        public void setId(String id){
            this.id=id;
        }
        public Attributes getAttribute(){
            return new Attributes("check","12lb","15lb",100);
        }
        
        public List<Attributes> getAttributes(){
            List<Attributes> ats = new ArrayList<Attributes>();
            
            return ats;
        }
        
        public static class Attributes {
            public String name;
            public String weight;
            public String height;
            public int capacity;
            
            public Attributes(String name,String weight,String height,int capacity){
                this.name=name;
                this.weight=weight;
                this.height=height;
                this.capacity=capacity;
            }
        
            public Attributes(){
                
            }
            public String toString(){
                return this.name+" "+this.weight+"  "+this.height+" "+this.capacity;
            }
            
            public void setName(String name){
                this.name=name;
            }
            public void setWeight(String weight){
                this.weight =weight;            
            }
            public void setHeight(String height){
                this.height=height;
            }
            
            public void setCapacity(int cap){
                this.capacity=cap;
            }
        }
    }
    
    公共类容器{
    公共字符串id;
    公共容器(){
    }
    公共容器(字符串id){
    这个.id=id;
    }
    公共无效集合id(字符串id){
    这个.id=id;
    }
    公共属性getAttribute(){
    返回新属性(“检查”、“12磅”、“15磅”、“100”);
    }
    公共列表getAttributes(){
    列表ats=新的ArrayList();
    返回ats;
    }
    公共静态类属性{
    公共字符串名称;
    公共弦权;
    公共线高度;
    公共能力;
    公共属性(字符串名称、字符串重量、字符串高度、整数容量){
    this.name=name;
    这个。重量=重量;
    这个。高度=高度;
    这个。容量=容量;
    }
    公共属性(){
    }
    公共字符串toString(){
    返回this.name+“”+this.weight+“”+this.height+“”+this.capacity;
    }
    公共void集合名(字符串名){
    this.name=name;
    }
    公共空隙设置重量(管柱重量){
    重量=重量;
    }
    公共空间设置高度(字符串高度){
    这个。高度=高度;
    }
    公共空间设置容量(内部上限){
    这个。容量=上限;
    }
    }
    }
    
    我是否需要通过调用X类上的newInstance()方法再次创建实例

    不,根据您的解释,您已经有了一个对象X。您不需要创建任何类型的新对象

    要调用对象X的方法,我必须调用method.invoke()吗 每一次?假设X对象有5个方法,找到该方法 并使用method.invoke调用该方法


    反射是运行时的事情。您不知道要使用的声明(或静态)类型。您基本上只使用
    对象
    接口/契约。因此,您需要通过反射实用程序执行所有操作。如果要调用对象的方法,则需要检索相应的
    方法
    对象,并使用正确的参数调用其
    调用(..)
    方法。

    这取决于定义X类的classloader。如果是父类加载器,则可以简单地强制转换返回值:

    X x = (X) my.invoke(inst, obj);
    
    然后像其他java对象一样使用它

    如果X是由自定义类加载器定义的,它会变得更复杂,因为X的定义对于父类加载器加载的类是不可见的。因此,这些类不能在源代码中引用X的方法和字段。通常的解决方法是在父类加载器中有一个接口(我们称之为Y),该接口由自定义类加载器中的X实现。由于这些方法是在Y中声明的,因此即使调用它们执行类X中的实现,也可以从父类装入器访问它们


    如果您也不能这样做,您仍然可以使用反射来调用这些方法。

    是的,如果您在编译时不知道方法头,您只能通过
    method.invoke()调用。更简单的解决方案之一是定义驻留在专利类加载器上下文中的公共接口(您需要在编译时引用接口)。然后,您加载的类将实现此接口。这将定义您可以针对实现调用的内容。当您放置类时,您只需将实例强制转换到接口。。。