java反射与类加载器的知识点小结

反射

* 反射 : 通过另一种动态手段做之前的事情, 比如创建对象, 访问属性, 调用方法
@Test
public void test2() {
    try {
        // 手工加载类模板, 类的全限定名称必须是 所有包名.类名
        Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
        Object object = clazz.newInstance(); // 直接由类模板创建对象. 无参构造器
        System.out.println(object);
    } catch (ClassNotFoundException e) { // 提供的类名错误, 或 类不存在.
        e.printStackTrace();
    } catch (IllegalAccessException e) { // 没有对访问的成员有访问权限.
        e.printStackTrace();
    } catch (InstantiationException e) { // 实例化失败, 可能由于构造器没有提供.
        e.printStackTrace();
    }
}
通过反射给对象的属性赋值
@Test
public void test3() {
    try {
        // 手工加载类模板, 类的全限定名称必须是 所有包名.类名
        Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
        Object object = clazz.newInstance(); // 直接由类模板创建对象. 无参构造器
        System.out.println(object);

        //先找到name属性定义, 再配合object对象.
        Field nameField = clazz.getField("name");
        // 给属性赋值, 使用set方法
        nameField.set(object, "红康");//object.name = "红康";
        // 获取属性值, 使用get方法
        System.out.println(nameField.get(object));//System.out.println(object.name);

        Field ageField = clazz.getField("age2");;
        ageField.set(object, 30); // object.age = 30
        System.out.println(ageField.get(object));

        Field genderField = clazz.getField("gender");
        genderField.set(object, "男");

        System.out.println(object);
    } catch (ClassNotFoundException e) { // 提供的类名错误, 或 类不存在.
        e.printStackTrace();
    } catch (IllegalAccessException e) { // 没有对访问的成员有访问权限.
        e.printStackTrace();
    } catch (InstantiationException e) { // 实例化失败, 可能由于构造器没有提供.
        e.printStackTrace();
    } catch (NoSuchFieldException e) { // 属性名错误 或 属性不存在.
        e.printStackTrace();
    }
}
突破封装. 暴力反射
 Field nameField = clazz.getDeclaredField("name");// getDeclaredField可以获取本类中所有声明的属性, 包括私有的
 nameField.setAccessible(true); // 突破封装. 暴力反射
@Test
public void test4() {
    try {
        Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
        Object object = clazz.newInstance();
        // getField只能获取本类或父类继承的公共属性.
        //Field nameField = clazz.getField("name");
        // getDeclaredField可以获取本类中所有声明的属性, 包括私有的.
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true); // 突破封装. 暴力反射
        System.out.println(nameField);
        nameField.set(object, "红康");
        System.out.println(nameField.get(object));

        Field ageField = clazz.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(object, 30);

        Field genderField = clazz.getDeclaredField("gender");
        genderField.setAccessible(true);
        genderField.set(object, "男");

        System.out.println(object);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) { // 非法访问.
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}
类模板和接口列表
@Test
public void test5() throws Exception {
    Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
    String name = clazz.getName();
    System.out.println(name);
    Class superclass = clazz.getSuperclass(); // 获取父类的类模板
    System.out.println(superclass);
    Class[] interfaces = clazz.getInterfaces(); // 获取本类实现的接口列表
    for (int i = 0; i < interfaces.length; i++) {
        System.out.println(interfaces[i]);
    }
}
int.class和Integer.class
@Test
public void test7() throws IllegalAccessException, InstantiationException {
    Class clazz1 = Integer.class; // clazz1代表Integer类型.
    Class clazz2 = int.class; // 基本数据类型的 类模板 只能通过基本类型.class获取
    // 基本数据类型的类型模板, 只能做一个事情 , 就是标识一下此类型.
    System.out.println(clazz1 == clazz2);

    boolean b = clazz2.isPrimitive(); // 判断clazz2代表的类型是否是基本类型.
    System.out.println(b);
    //Object obj = clazz2.newInstance();

    System.out.println(boolean.class);
}
获取类模板对象的四种方法
@Test
public void test6() throws ClassNotFoundException {
    // 获取类模板对象的方法
    // 1) 已知类, 并且类已经提供好的情况下, 通过类的静态属性class直接获取, 效率最好, 最简单.
    Class clazz1 = Teacher.class;
    // 2) 根据对象进一步获取对象所属的类模板
    Class clazz2 = new Teacher("a", 2, "b").getClass();
    System.out.println(clazz1 == clazz2);
    // 3) 根据类的全限定名称, 动态手工加载类
    Class clazz3 = Class.forName("com.atguigu.javase.reflect.Teacher");
    System.out.println(clazz1 == clazz3);

    // 4) 通过类加载器对象来手工加载类
    Class clazz4 = this.getClass().getClassLoader().loadClass("com.atguigu.javase.reflect.Teacher");
    System.out.println(clazz3 == clazz4);
}
类加载器3个层次(了解)
@Test
public void test8() throws IOException {
    // 最普通的就是系统类加载器, 也称为应用程序类加载器
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    System.out.println(systemClassLoader);

    // 扩展类加载器, 它不是核心, 它负责加载的类是 jdk/jre/lib/ext目录下的所有.jar文件
    ClassLoader extentionClassLoader = systemClassLoader.getParent();
    System.out.println(extentionClassLoader);

    // 类加载器3个层次, 最底层的是BootstrapClassLoader 引导类加载器, 是最核心的.
    // 因为它负责加载的类是 jdk/jre/lib下的所有.jar文件.
    ClassLoader bootstrapClassLoader = extentionClassLoader.getParent();
    System.out.println(bootstrapClassLoader);

    // 双亲委派机制.
    /*
    当加载类时, 首先会让系统类加载器尝试加载, 它不敢, 把任务委派给扩展类加载器, 扩展类加载器仍然要继续委派给引导类加载器
    如果要加载类不是核心类, 请求被驳回, 驳回给扩展类加载器, 扩展类加载器检查, 如果不归它加载, 继续驳回给系统类加载器
    系统类加载器再加载类. 但是如果加载的类是核心类, 委派后引导类加载器会当仁不让.
    这样的结果就是不同层次的类,由不同层次的类加载器来加载*/


    // 只要是项目能使用的类或文件, 都可以通过它来获取流, 用途更宽
    //InputStream in = systemClassLoader.getResourceAsStream("com/sun/corba/se/impl/logging/LogStrings.properties");
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("test.properties");
    Properties properties = new Properties();
    properties.load(in);

    Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry<Object, Object> next = iterator.next();
        System.out.println(next);
    }
}
通过反射获取构造器对象
@Test
public void test9() {
    try {
        Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
        //Object obj = clazz.newInstance();
        //public Teacher(String name, int age, String gender) {
        // 1) 获取到构造器对象
        Constructor constructor = clazz.getConstructor(String.class, int.class, String.class);// 构造方法的形参的类型(每个类型都用相应的Class对象来描述)列表
        // 2) 通过构造器对象的方法来创建实例, 实参列表必须要和方法的形参列表完全一致
        Object object = constructor.newInstance("芳芳", 20, "女");// 实际调用构造方法时的实参列表, new Teacher("芳芳", 20, "女");
        System.out.println(object);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}
通过反射获取方法
@Test
public void test10() {
    try {
        Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
        Object object = clazz.newInstance();

        //((Teacher)object).lesson("JavaSE", 202);
        // 1) 先获取方法代码对象, getMethod只能获取公共方法, 包括从父类继承的.
        Method size = clazz.getMethod("size");
        Object invoke = size.invoke(object);
        System.out.println("size : " + invoke);

        //Method lessonMethod = clazz.getMethod("lesson", String.class, int.class);// 第1个参数是方法名, 后面是方法需要的参数类型列表
        Method lessonMethod = clazz.getDeclaredMethod("lesson", String.class, int.class);// 第1个参数是方法名, 后面是方法需要的参数类型列表
        lessonMethod.setAccessible(true);
        // 2) 方法再和this对象配合
        Object retValue = lessonMethod.invoke(object, "JavaSE", 202);
        System.out.println("返回值:" + retValue);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) { // 还没有访问权限时, 访问成员.
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) { // 未找到方法异常, 方法名错误, 或 参数类型错误
        e.printStackTrace();
    } catch (InvocationTargetException e) { // 调用的目标方法真的出现异常时, 捕获这个异常.
        e.printStackTrace();
    }


}
获取静态属性
@Test
public void test11() {
    Class clazz = null;
    try {
        clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
        Field school = clazz.getField("school");
        Object o = school.get(null); // school是静态属性, 不需要对象
        System.out.println(o);

        Method test = clazz.getMethod("test");
        test.invoke(null); // 参数中的对象是什么都无所谓, 因为会在执行时忽略它
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }


}
通过反射获取注解中的属性值
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)   //必须是运行时
@interface MyAnnotation {
    int id() default 100;
    String value() default "abc";
}
@Test
public void test12() throws ClassNotFoundException, NoSuchMethodException {
    Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
    Annotation annotation = clazz.getAnnotation(MyAnnotation.class);
    System.out.println(annotation);

    Method lesson = clazz.getDeclaredMethod("lesson", String.class, int.class);
    MyAnnotation annotation1 = lesson.getAnnotation(MyAnnotation.class);
    System.out.println(annotation1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值