java基础(四)

java类加载器和反射机制

类加载器
  • 负责将.class文件加载到内在中,并为之生成对应的Class对象。
类加载器的组成
  • Bootstrap ClassLoader 根类加载器
  • Extension ClassLoader 扩展类加载器
  • Sysetm ClassLoader 系统类加载器
类加载器的作用
  • Bootstrap ClassLoader 根类加载器
    • 也被称为引导类加载器,负责Java核心类的加载比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
  • Extension ClassLoader 扩展类加载器
    • 负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录
  • Sysetm ClassLoader 系统类加载器
    • 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

反射机制

  • JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射的一些常用方法:

创建对象
newInstance()
获取构造方法
getConstructors
getDeclaredConstructors
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value)
获取所有方法
getMethods
getDeclaredMethods
获取单个方法
getMethod
getDeclaredMethod
暴力访问(private修饰)
method.setAccessible(true);

但想要这样使用,首必须得到class文件对象,就是得到Class类的对象,而得到Class类的对象有几种方式:

// 方式1(基本不用)
Person p = new Person();
Class c = p.getClass();
// 方式2(实际开发不怎么用)
Class c3 = Person.class;
// 方式3是通过字符串加载,而不是一个具体的类名。这样可以把字符串配置到配置文件中(比如:要求一个APP支持微信支付,支付宝支付,银联支付,以后甚至更多的支付方式,这样可以通过一个接口定义支付过程的几种状态,通过反射机制和面向对象的特性把配置文件配置此接口的实现类,以达到不修改任何代码下更换支付方式)
Class c4 = Class.forName(“cn.itcast_01.Person”);

反射获取成员变量并赋值

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取所有的成员变量
        // Field[] fields = c.getFields();
        // Field[] fields = c.getDeclaredFields();
        // for (Field field : fields) {
        // System.out.println(field);
        // }

        /*
         * Person p = new Person(); p.address = "北京"; System.out.println(p);
         */

        // 通过无参构造方法创建对象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        // 获取单个的成员变量
        // 获取address并对其赋值
        Field addressField = c.getField("address");
        // public void set(Object obj,Object value)
        // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
        addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
        System.out.println(obj);

        // 获取name并对其赋值
        // NoSuchFieldException
        Field nameField = c.getDeclaredField("name");
        // IllegalAccessException
        nameField.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
        nameField.set(obj, "李四");
        System.out.println(obj);

        // 获取age并对其赋值
        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj, 27);
        System.out.println(obj);
    }
}

反射获取成员方法并赋值

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取所有的方法
        // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
        // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
        // for (Method method : methods) {
        // System.out.println(method);
        // }

        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        /*
         * Person p = new Person(); p.show();
         */

        // 获取单个方法并使用
        // public void show()
        // public Method getMethod(String name,Class<?>... parameterTypes)
        // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
        Method m1 = c.getMethod("show");
        // obj.m1(); // 错误
        // public Object invoke(Object obj,Object... args)
        // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
        m1.invoke(obj); // 调用obj对象的m1方法

        System.out.println("----------");
        // public void method(String s)
        Method m2 = c.getMethod("method", String.class);
        m2.invoke(obj, "hello");
        System.out.println("----------");

        // public String getString(String s, int i)
        Method m3 = c.getMethod("getString", String.class, int.class);
        Object objString = m3.invoke(obj, "hello", 100);
        System.out.println(objString);
        // String s = (String)m3.invoke(obj, "hello",100);
        // System.out.println(s);
        System.out.println("----------");

        // private void function()
        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);
    }
}

ArrayList的一个对象,在这个集合中添加一个字符串数据:

public class ArrayListDemo {
    public static void main(String[] args) throws NoSuchMethodException,
            SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        // 创建集合对象
        ArrayList<Integer> array = new ArrayList<Integer>();

        // array.add("hello");
        // array.add(10);

        Class c = array.getClass(); // 集合ArrayList的class文件对象
        Method m = c.getMethod("add", Object.class);

        m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
        m.invoke(array, "world");
        m.invoke(array, "java");

        System.out.println(array);
    }
}

总结:
通过反射可以修改java底层代码以达到我们所需要的功能,当然还有更深入知识需要去了解,去研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值