JavaSE学习笔记 - 反射技术

概述

  • 反射是一种强大的工具,可以用来编写能够动态操纵 Java 代码的程序,通过反射机制我们可以操作字节码文件。反射机制将类的各个部分封装成了对象,在程序运行的过程中我们可以操作这些对象(在操作一个类对象的时候我们可以操作其方法成员变量等)。这样可以使得程序解耦,提高了程序的可扩展性。

Java 代码的三个阶段

  • 源代码阶段:编写类文件,然后添加成员变量,成员方法等,代码编译后生成字节码文件,此时代码还未被加载进内存。
  • Class 类对象阶段:Class 类对象使用类加载器将字节码文件加载进内存,此时内存中就会产生一个唯一的 Class 类对象来标识这个类中的各项信息,Class 类对象中又包含了描述成员变量的 Field 对象、描述构造方法的 Constructor 对象和描述成员方法的 Method 对象。
  • 运行时阶段:new 一个新的类对象。

Class

  • 在程序运行的时候,系统始终为所有的对象维护一个运行时的类型标识,这个信息会跟踪每一个对象所属的类,我们使用 Java 中的 Class 类就可以访问这些被记录的信息。

获取 Class 对象的三种方式

  • Class.forName("全类名"):将字节码文件加载进内存,配置文件常用
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cls = Class.forName("java.lang.String");
        System.out.println(cls);//class java.lang.String
    }
}
  • 类名.class:常用于参数的传递
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cls = Class.forName("java.lang.String");
        Class cls1 = String.class;
        System.out.println(cls.hashCode());//460141958
        System.out.println(cls1);//class java.lang.String
    }
}
  • 对象.getClass():常用于获取对象字节码
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cls = Class.forName("java.lang.String");
        Class cls1 = String.class;
        String str = "";
        Class cls2 = str.getClass();
        //字节码文件在内存中只被加载一次
        //不管使用什么方式获取到的Class对象都是同一个
        System.out.println(cls.hashCode());//460141958
        System.out.println(cls1.hashCode());//460141958
        System.out.println(cls2);//class java.lang.String
    }
}

Class 类常用 API

  • 获取 public 修饰的成员变量
//获取 public 修饰的成员变量
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class cls = Class.forName("java.lang.String");
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        Field field = cls.getField("CASE_INSENSITIVE_ORDER");
        System.out.println(field.getName());
    }
}


//获取所有的成员变量
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class cls = Class.forName("java.lang.String");
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        Field field = cls.getDeclaredField("hash");
        System.out.println(field.getName());
    }
}
  • 获取构造函数
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        //得到所有公共的构造函数对象
        Constructor[] constructors = cls.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        //得到特定的公共构造函数对象
        Constructor constructor = cls.getConstructor(String.class);
        System.out.println(constructor);
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        //得到所有的构造函数对象
        Constructor[] constructors = cls.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        //得到特定的构造函数对象
        Constructor constructor = cls.getDeclaredConstructor(String.class);
        System.out.println(constructor);
    }
}
  • 获取成员方法
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        //获取所有公共的成员方法
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //获取特定的公共的成员方法
        System.out.println("-------");
        Method method = cls.getMethod("toLowerCase", Locale.class);
        System.out.println(method);
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        //获取所有的成员方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //获取特定的成员方法
        System.out.println("-------");
        Method method = cls.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class);
        System.out.println(method);
    }
}
  • 有关 Class 类的 API
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        System.out.println(cls.getName());//java.lang.String
        System.out.println(cls.getSimpleName());//String

        //获取父类
        Class superclass = cls.getSuperclass();
        System.out.println(superclass);//class java.lang.Object
        System.out.println(superclass.isInterface());//false

        //获取包对象
        Package aPackage = cls.getPackage();
        System.out.println(aPackage.getName());//java.lang

    }
}

Constructor

public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        //得到所有的构造函数对象
        Constructor[] constructors = cls.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
            //方法名
            System.out.println(constructor.getName());
            //修饰符
            System.out.println(Modifier.toString(constructor.getModifiers()));
            //参数类型
            Class[] parameterTypes = constructor.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + " ");
            }
            System.out.println();
            System.out.println("-------------------------------------");
        }
    }
}


//创建对象
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = String.class;
        String str = (String) cls.newInstance();
    }
}

Field

public class Main {
    public static void main(String[] args) throws Exception {
        String str = "1111";
        Class cls = Class.forName("java.lang.String");
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
            System.out.println(Modifier.toString(field.getModifiers()));
            System.out.println(field.getType().getSimpleName());
            System.out.println(field.getName());
            //System.out.println(field.get(str));
            System.out.println("-----------------------------------------------");
        }

    }
}
//为对象的成员变量设置值
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = String.class;
        String str = (String) cls.newInstance();
        Field field = cls.getDeclaredField("value");
        //不是公共的成员变量是需要暴力反射,默认只能修改非公共成员变量
        field.setAccessible(true);
        System.out.println(field);
        System.out.println(field.get(str));//[C@4554617c
        System.out.println(str);//
        field.set(str, new char[]{'1', '1'});
        System.out.println(field.get(str));//[C@74a14482
        System.out.println(str);//11
    }
}

Method

public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("java.lang.String");

        //获取所有的成员方法
        Method[] methods = cls.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
            System.out.println(Modifier.toString(method.getModifiers()));
            System.out.println(method.getReturnType().getSimpleName());
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println(parameterType.getSimpleName());
            }
            //是否有可变参数
            System.out.println(method.isVarArgs());
            System.out.println(method.getName());
            System.out.println("-------------------------");
        }
    }
}

//执行类方法
public class Main {
    public static void main(String[] args) throws Exception {
        Class cls = String.class;
        String str = (String) cls.newInstance();
        Field field = cls.getDeclaredField("value");
        field.setAccessible(true);

        field.set(str, new char[]{'1', '1'});

        Method method = cls.getDeclaredMethod("length");
        System.out.println(method.invoke(str));

    }
}

配置文件操作类

配置文件

className = java.lang.String
methodName = length
fieldName = value

Properties + IO + 反射

public class Main {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();

        //方式一:利用当前类获取流,配置文件需要在src目录下
        ClassLoader classLoader = Main.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        properties.load(is); //要记得关闭流

        //方式二:首先获取文件路径,然后根据路径创建输入流
        //配置文件需要在根路径下
//        String path = Thread.currentThread().getContextClassLoader().getResource("pro.properties").getPath();
//        //System.out.println(path);
//        FileReader reader = new FileReader(path);
//        properties.load(reader);

        Class cls = Class.forName(properties.getProperty("className"));
        Object o = cls.newInstance();
        Field field = cls.getDeclaredField(properties.getProperty("fieldName"));
        field.setAccessible(true);
        field.set(o, new char[]{'a', 'b'});
        System.out.println(field.get(o));

        Method method = cls.getDeclaredMethod(properties.getProperty("methodName"));
        System.out.println(method.invoke(o));
    }
}

ResourceBundle + 反射

public class Main {
    public static void main(String[] args) throws Exception {
        //资源绑定器,配置文件需要放在根路径下
        ResourceBundle bundle = ResourceBundle.getBundle("pro");

        Class cls = Class.forName(bundle.getString("className"));
        Object o = cls.newInstance();
        Field field = cls.getDeclaredField(bundle.getString("fieldName"));
        field.setAccessible(true);
        field.set(o, new char[]{'a', 'b'});
        System.out.println(field.get(o));

        Method method = cls.getDeclaredMethod(bundle.getString("methodName"));
        System.out.println(method.invoke(o));
    }
}

反射方式反编译类框架

配置文件

className = java.util.ResourceBundle 

测试代码

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        //资源绑定器,配置文件需要放在根路径下
        ResourceBundle bundle = ResourceBundle.getBundle("pro");

        Class<?> cls = Class.forName(bundle.getString("className"));
        Package aPackage = cls.getPackage();
        //包
        if (aPackage != null) System.out.println("package " + aPackage.getName());
        System.out.println();
        //修饰符
        System.out.print(Modifier.toString(cls.getModifiers()) + " ");
        //类名
        System.out.print(cls.getSimpleName() + " ");
        //父类
        Class<?> superclass = cls.getSuperclass();
        if (!superclass.equals(Object.class)) {
            System.out.print( "extends " + superclass.getSimpleName() + " ");
        }
        //接口
        Class<?>[] interfaces = cls.getInterfaces();
        StringBuilder _interfaces = new StringBuilder();
        if(interfaces.length == 0) {
            _interfaces.append("");
        } else {
            _interfaces.append(" implements ");
        }
        for (int i = 0; i < interfaces.length; i++) {
            _interfaces.append(interfaces[i].getSimpleName());
            if (i != interfaces.length - 1) {
                _interfaces.append(", ");
            } else {
                _interfaces.append(" ");
            }
        }
        System.out.println(_interfaces + "{");

        System.out.println();
        //获取成员变量
        getDeclaredFields(cls);
        //获取构造方法
        getDeclaredConstructors(cls);
        //获取成员方法
        getMethods(cls);

        System.out.println("}");
    }

    private static void getDeclaredFields(Class<?> cls) {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.print("\t");
            //修饰符
            System.out.print(Modifier.toString(field.getModifiers()) + " ");
            //数据类型
            System.out.print(field.getType().getSimpleName() + " ");
            //变量名
            System.out.println(field.getName() + ";");
            //System.out.println(field);
            //System.out.println("----------------");
        }
        System.out.println();
    }

    private static void getDeclaredConstructors(Class<?> cls) {
        Constructor<?>[] constructors = cls.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            //修饰符
            System.out.print("\t");
            if (constructor.getModifiers() != 0)
                System.out.print(Modifier.toString(constructor.getModifiers()) + " ");
            //方法名
            System.out.print(cls.getSimpleName() + "(");
            //参数
            Class<?>[] typeParameters = constructor.getParameterTypes();
            StringBuilder _typeParameters = new StringBuilder();
            for (int i = 0; i < typeParameters.length; i++) {
                if (i != 0) {
                    _typeParameters.append(", ");
                }
                _typeParameters.append(typeParameters[i].getSimpleName());
            }
            System.out.println(_typeParameters + "){};");
            //System.out.println(constructor);
            //System.out.println("---------------------------");
        }
        System.out.println();
    }

    private static void getMethods(Class<?> cls) {
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
            System.out.print("\t");
            //修饰符
            System.out.print(Modifier.toString(method.getModifiers()) + " ");
            //返回值
            System.out.print(method.getReturnType().getSimpleName() + " ");
            //方法名
            System.out.print(method.getName() + "(");
            //参数
            Class<?>[] parameterTypes = method.getParameterTypes();
            StringBuilder _parameterTypes = new StringBuilder();
            for (int i = 0; i < parameterTypes.length; i++) {
                if (i != 0) {
                    _parameterTypes.append(", ");
                }
                _parameterTypes.append(parameterTypes[i].getSimpleName());
            }
            System.out.println(_parameterTypes + "){};");
            //System.out.println(method);
            //System.out.println("------------------------");
        }
        System.out.println();
    }
}
上一篇:初学 Python 笔记【二十六】类方法,类属性,静态方法


下一篇:python 3 基础之单例模式