java反射基础与动态编译

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

获取Class对象

在这里插入图片描述

反射常见作用

在这里插入图片描述
bean.User

package bean;

public class User {
    
    
    private int id;
    private int age;
    private String uname;

    public User(){
    
    

    }

    public User(int id, int age, String uname) {
    
    
        this.id = id;
        this.age = age;
        this.uname = uname;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String getUname() {
    
    
        return uname;
    }

    public void setUname(String uname) {
    
    
        this.uname = uname;
    }
}
package reflect;

// 测试各种类型(class,interface,enum,annotation,primitive type,void)对应的java.lang.Class对象的获取方式
public class Demo01 {
    
    

    public static void main(String[] args) {
    
    

        String path = "bean.User";

        try {
    
    
            Class clz = Class.forName(path);
            // 对象是表示和封装一些数据, 一个类被加载后,JVM会创建一个对应类的Class对象, 类的整个结构信息会放到对应的Class对象中
            // 这个Class对象就像一面镜子一样, 通过这面镜子可以看到类的全部信息
            System.out.println(clz);

            Class strClz = String.class;
            Class strClz2 = "".getClass();  // 对象.getClass();

            System.out.println(strClz == strClz2);  // true

            Class intClass = int.class;

            int[] arr01 = new int[10];
            int[] arr02 = new int[30];
            int[][] arr03 = new int[30][3];
            double[] arr04 = new double[10];

            System.out.println(arr01.getClass().hashCode());
            System.out.println(arr02.getClass().hashCode());
            System.out.println(arr03.getClass().hashCode());
            System.out.println(arr04.getClass().hashCode());

        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

应用反射的API, 获取类的信息(类的名字, 属性, 构造器等)

package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 应用反射的API, 获取类的信息(类的名字, 属性, 构造器等)
 */
public class Demo02 {
    
    

    public static void main(String[] args) {
    
    

        String path = "bean.User";
        try {
    
    

            Class clz = Class.forName(path);

            // 获取类的名字
            System.out.println(clz.getName());  // 获取包名+类名
            System.out.println(clz.getSimpleName());  // 获取类名

            // 获取属性信息
            Field[] fields = clz.getFields();  // 只能获取public的field
            fields = clz.getDeclaredFields();  // 获得所有的field
            Field field = clz.getDeclaredField("uname");  // 获取指定的field

            System.out.println(fields.length);
            for (Field temp: fields) {
    
    
                System.out.println("属性: " + temp);
            }
            // 获取方法信息
            Method[] methods = clz.getDeclaredMethods();

            // 如果方法有参数, 则必传参数类型对应的Class对象
            Method m01 = clz.getDeclaredMethod("getUname", null);
            // 方法名, 参数类型对象的Class对象(防止重载)
            Method m02 = clz.getDeclaredMethod("setUname", String.class);

            for (Method m: methods) {
    
    
                System.out.println("方法: " + m);
            }

            // 获得构造方法信息
            Constructor[] constructors =  clz.getDeclaredConstructors();

            Constructor c = clz.getDeclaredConstructor(null);
            c = clz.getDeclaredConstructor(int.class, int.class, String.class);

            System.out.println(c);

            for (Constructor temp: constructors) {
    
    
                System.out.println("构造方法: " + temp);
            }

        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

通过反射API动态的操作:构造器,方法,属性

package reflect;

import bean.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 通过反射API动态的操作:构造器,方法,属性
 */
public class Demo03 {
    
    

    public static void main(String[] args) {
    
    

        String path = "bean.User";
        try {
    
    

            Class clz = Class.forName(path);

            // 通过动态调用构造方法,构造对象
            User u = (User) clz.getDeclaredConstructor().newInstance();

            System.out.println(u);
            // 有参数构造
            Constructor<User> c = clz.getDeclaredConstructor(int.class, int.class, String.class);

            User u2 = c.newInstance(1001, 19, "xiaobo");
            System.out.println(u2.getUname());

            // 通过反射API调用普通方法
            User u3 = (User)clz.newInstance();
            Method method = clz.getDeclaredMethod("setUname", String.class);
            method.invoke(u3, "xiaoli");  // u3.setUname("xiaoli");
            System.out.println(u3.getUname());

            // 通过反射API操作属性
            User u4 = (User)clz.newInstance();
            Field f = clz.getDeclaredField("uname");
            f.setAccessible(true);  // 这个属性不需要做安全检查了,可以直接访问
            f.set(u4, "xiaomei");  // 通过反射直接写属性
            System.out.println(u4.getUname());
            System.out.println(f.get(u4));  // 通过反射直接读属性


        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

反射机制性能

在这里插入图片描述

反射操作泛型

在这里插入图片描述

package reflect;

import bean.User;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * 通过反射获取泛型信息
 */
public class Demo04 {
    
    

    public void test01(Map<String, User> map, List<User> list){
    
    
        System.out.println("Demo04.test01()");
    }

    public Map<Integer, User> test02(){
    
    
        System.out.println("Demo04.test02()");
        return null;
    }

    public static void main(String[] args) {
    
    

        try {
    
    

            // 获得指定方法参数泛型信息
            Method m = Demo04.class.getMethod("test01", Map.class, List.class);
            Type[] t = m.getGenericParameterTypes();

            for (Type paramType: t) {
    
    
                System.out.println("#" + paramType);
                if (paramType instanceof ParameterizedType){
    
    

                    Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
                    for (Type genericType: genericTypes) {
    
    
                        System.out.println("泛型类型:" + genericType);
                    }
                }
            }

            // 获得指定方法返回值泛型类型
            Method m2 = Demo04.class.getMethod("test02", null);
            Type returnType = m2.getGenericReturnType();

            if (returnType instanceof ParameterizedType){
    
    

                Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
                for (Type genericType: genericTypes) {
    
    
                    System.out.println("返回值, 泛型类型:" + genericType);
                }
            }

        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

反射操作注解(annotation)

在这里插入图片描述

动态编译

在这里插入图片描述

JavaComplier动态编译

在这里插入图片描述

动态运行

在这里插入图片描述

package dynamicCompiler;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Demo01 {
    
    

    public static void main(String[] args) throws IOException {
    
    

        // 通过IO流操作,将字符串存储成一个临时文件(Hi.java), 然后调用动态编译方法
        String str = "public class Hi{public static void main(String[] args){System.out.println(\"Hello World\");}}";
        FileOutputStream os = new FileOutputStream("Hi.java");
        os.write(str.getBytes());
        os.flush();
        os.close();


        // 获得java编译器
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//        int result = compiler.run(null, null, null, "/home/sweetheart/eclipse-workspace/Test01/src/HelloWorldAWT.java");
        int result = compiler.run(null, null, null, "./Hi.java");

        System.out.println(result==0? "编译成功": "编译失败");

        // 通过Runtime调用执行类
        Runtime run = Runtime.getRuntime();
        Process process = run.exec("java -cp ./  Hi");
        InputStream in = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String info = "";

        while ((info=reader.readLine())!=null){
    
    
            System.out.println(info);
        }
        
        // 通过反射进行加载调用
        try {
    
    

            URL[] urls = new URL[]{
    
    new URL("file:/" + "home/sweetheart/IdeaProjects/annotation/")};
            URLClassLoader loader = new URLClassLoader(urls);
            Class c = loader.loadClass("Hi");

            // 调用加载类的main方法
            Method m = c.getMethod("main", String[].class);
            m.invoke(null, (Object)new String[]{
    
    "aa", "bb"});
            // 不加Object强转相当于这样调用
            // public static void main("aa", "bb"){..};

        }catch (Exception e){
    
    

            e.printStackTrace();
        }
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46456049/article/details/113834916
今日推荐