24.类的加载机制和反射.md

1类的加载连接和初始化

1.1类的加载过程

类的加载过程简单为分为三步:加载->连接->初始化


1.2类的加载器

1.2.1类的加载机制

  • 全盘加载:
    使用一个类负责加载一个Class文件,该Class依赖和负责的Class都由这个类加载器负责加载
  • 父类加载:
    先让这个类的父类加载器加载这个类,只有当这个父加载器无法加载时候,才从自己的类路径中加载该类
  • 缓存机制:
    所有被加载过的类都会被缓存,当程序需要某个类的时候,类加载器先从缓冲区寻找这个类,只有当这个类在缓存区不存在时候,才会读取对应的二进制文件,转换为Class对象,所以每次修改了Class后,需要重启JVM才能生效

加载器的继承的顺序,其中自定义的加载器通过继承ClassLoader来实现:

依照这个顺序,可以得到一个类加载的顺序


1.通过反射获得类的信息

package com.liyue.studycode.classreflect;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
 
@Retention(value = RetentionPolicy.RUNTIME)
@interface Anno{}
@SuppressWarnings(value = "unused")
public class BaseClass {
    //declare a private constructor.
    private BaseClass(){};
     
    //decalre a public constructor
    public BaseClass(int id){
        System.out.println("excute a public constructor");
    }
     
    //delcare a void function 
    public void fun(){
        System.out.println("excute a void function");
    };
     
    //declare a function with paramter
    public void test(String name){
        System.out.println("excute a function with paramter: " + name);
    }  
     
}
package com.liyue.studycode.classreflect;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
 
public class RefectMain {
 
    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        //get class's object
        Class<BaseClass> cl = BaseClass.class;
         
        //get all public constructor
        Constructor[] constructor = cl.getDeclaredConstructors();
        System.out.println("All of BaseClass's constuctor:");
        for(Constructor c : constructor){
            System.out.println(c);
        }
         
        //get all public method
        Method[] method = cl.getMethods();
        System.out.println("All of BaseClass's constuctor:");
        for(Method m : method){
            System.out.println(m);
        }
         
        //get designated method
        System.out.println("BaseClass's function with parameter named"
                + "test" + cl.getMethod("test", String.class) );
         
        //get all annotation of BaseClass
        Annotation[] an = cl.getAnnotations();
        System.out.println("All annotation of BaseClass:");
        for(Annotation a : an){
            System.out.println(a);
        }
         
        //get @SuppressWarnings
        System.out.println("BaseClass's SuppressWarnings:"
                + Arrays.toString(cl.getAnnotationsByType
                        (SuppressWarnings.class)));
         
        //get package
        System.out.println("BaseClass's package:"
                + cl.getPackage());
    }
 
}

2.Java 8新增的方法参数反射

如果将上例BaseClass.test方法改造一下:

public void test(String name, int num){
        System.out.println("excute a function with paramter: " + name);
    } 

那么可以这么获取参数

Class<BaseClass> cl = BaseClass.class;
        Method m = cl.getMethod("test", String.class, int.class);     
        Parameter[] ps = m.getParameters();
        System.out.println(m.getParameterCount());
        for(Parameter p : ps){
            System.out.println(p.getName());
            System.out.println(p.getType());
            System.out.println(p.getParameterizedType());        
        }

3.通过反射操作对象
3.1创建对象
3.1.1使用newInstance方法

package com.liyue.studycode.objectfactory;
 
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Properties;
 
 
public class ObjectFactory {
    //declare a map to save object
    private HashMap<String, Object> objectPool = new HashMap<>();
     
    //declare function to new class,return object by class name
    private Object createObject(String targetClassNmae)
            throws Exception{
        Class<?> cl = Class.forName(targetClassNmae);
        return cl.newInstance();
    }
     
    //read property file
    public void initObjectPool(String fileName) 
            throws Exception{
        Properties pRead = new Properties();
        pRead.load(new FileInputStream(fileName));
        for(String name : pRead.stringPropertyNames()){
            objectPool.put(name, createObject(pRead.getProperty(name)));
        }      
    }
     
    //return object of Map
    public Object getObject(String name){
        return objectPool.get(name);
    }  
}

定义一个属性文件,保存需要读取的信息

a = java.util.Date
b = javax.swing.JFrame
package com.liyue.studycode.objectfactory;
 
public class ObjectFactoryPrint {
 
    public static void main(String[] args) {
        ObjectFactory of = new ObjectFactory();
        try {
            of.initObjectPool("Properties//myclassrelectconfig.ini");
            System.out.println(of.getObject("a"));
            System.out.println(of.getObject("b"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3.1.2使用Constructor创建

try {
    Class<?> cl = Class.forName("javax.swing.JFrame");
    Constructor c = cl.getConstructor(String.class);
    Object obj = c.newInstance("哈哈");
    System.out.println(obj);
     
} catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

3.2调用方法

package com.liyue.studycode.objectfactory;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
 
public class ObjectFactoryPrint {
 
    public static void main(String[] args) throws Exception{
        try {
            //call method forName
            Class<?> cl = Class.forName("javax.swing.JFrame");
            //get constructor
            Constructor c = cl.getConstructor(String.class);
            //get instance of JFrame
            Object obj = c.newInstance("");
            //get method setTitle
            Method md = cl.getMethod("setTitle", String.class);
            //call invoke
            md.invoke(obj, "哈哈");
            System.out.println(obj);
             
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3.3访问成员变量

package com.liyue.studycode.fieldreflect;
 
import java.lang.reflect.Field;
 
public class FieldReflectPrint {
 
    public static void main(String[] args) 
            throws Exception{
        Emploee e = new Emploee();
        Class<?> cl = e.getClass();
        //getDeclaredField get field of the class
        /*get name*/
        Field nameField = cl.getDeclaredField("name");
        //Set the accessible flag for this object
        nameField.setAccessible(true);
        //set new value
        nameField.set(e, "张三");
        /*get age*/
        Field agefield = cl.getDeclaredField("age");
        //Set the accessible flag for this object
        agefield.setAccessible(true);
        //set new value
        agefield.set(e, 29);
         
        System.out.println(e);
         
    }
}

3.4获取数组

4.使用反射生成JDK动态代理

4.1创建动态代理

package com.liyue.study.dynamicobject;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class MyInvokationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(args != null){
            System.out.println("下面是执行该方法时候传入的实参:");
            for (Object v : args) {
                System.out.println(v);
            }
        }
        else{
            System.out.println("调用该方法没有实参。");
        }
        return null;
    }
 
}
package com.liyue.study.dynamicobject;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
public class DynamicObjectPrint {
    public static void main(String[] args) throws Exception{
        InvocationHandler handler = new MyInvokationHandler();
        //使用InvocationHandler生成一个动态对象
        Person p = (Person)Proxy.newProxyInstance(Person.class.getClassLoader()
                , new Class[]{Person.class}
                , handler);
        p.walk();
        p.sayHello("李四");
    }
}

4.2动态代理和AOP

package com.liyue.studycode.aop;
 
public interface Bird {
    //definition two abstract function
    void info();
    void fly();
}
package com.liyue.studycode.aop;
 
public class Duck implements Bird {
 
    @Override
    public void info() {
        // TODO Auto-generated method stub
        System.out.println("I am a duck!");
    }
 
    @Override
    public void fly() {
        // TODO Auto-generated method stub
        System.out.println("I can fly!");
    }
}
package com.liyue.studycode.aop;
 
public class BirdUtil {
    //This is the first simulation function 
    public void fun1(){
        System.out.println("This is birdutil function 1!");
    }
    //This is the second simulation function 
    public void fun2(){
        System.out.println("This is birdutil function 2!");
    }
}
package com.liyue.studycode.aop;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class MyInvocationHandler implements InvocationHandler {
    //The object need to agented
    private Object target;
    //setter
    public void setTarget(Object target) {
        this.target = target;
    }
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
            throws Exception {
        BirdUtil bu = new BirdUtil();
        //simulate the first function
        bu.fun1();
        //use target to excute method
        Object result = method.invoke(target, args);
        //simulate the second function
        bu.fun2();
         
        return result;
    }
 
}
package com.liyue.studycode.aop;
 
import java.lang.reflect.Proxy;
 
import com.liyue.studycode.aop.MyInvocationHandler;
 
public class MyProxy {
    public static Object getProxy(Object target) 
            throws Exception{
        //create a MyInvocationHandler
        MyInvocationHandler mih = new MyInvocationHandler();
        //set target to mih
        mih.setTarget(target);
         
        return Proxy.newProxyInstance(target.getClass().getClassLoader()
                , target.getClass().getInterfaces()
                , mih);
    }
}

package com.liyue.studycode.aop;
 
import com.liyue.study.dynamicobject.MyProxy;
 
public class AopPrint {
 
    public static void main(String[] args) 
            throws Exception {
        //create a object of Duck
        Bird target = new Duck();
        Bird b = (Bird)MyProxy.getProxy(target);
        b.info();
        b.fly();
    }
 
}

有参构造的调用
有一个带参构造:

package pers.liyue.generic.test;
 
public class ReflectTest {
    public int num = 0;
    public double size = 0.00;
    private float bignum = 0;
     
    public ReflectTest(){
        System.out.println("Create class!");
    }
     
    public ReflectTest(int numb){
        System.out.println("Create class with args!" + numb);
    }
}

调用时候不能用默认的newInstance

public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        ReflectTest rt = new ReflectTest();
        rt.Fun1();
        //无参构造调用
        Class c = Class.forName("pers.liyue.generic.test.ReflectTest");
        ReflectTest o = (ReflectTest)c.newInstance();
        //有参构造调用
        Constructor ccc = c.getConstructor(new Class[]{int.class});
        ReflectTest b = (ReflectTest)ccc.newInstance(new Object[]{1});
    }
原文地址:https://www.cnblogs.com/bugstar/p/8492835.html