JavaSE(十七)反射

反射

  • reflect 高级特性

  • 反射 是框架的灵魂;

  • 反射:运行过程中 动态获取类的信息(获取类对象) 和对类进行操作的机制;

  • Java的程序的执行:

    • 1 编译 .java .class字节码文件 Student.java->Student.class

    • 2 运行 .class文件由类加载器 加载进JVM内存 形式 Class类型 类对象;

    • 类对象{成员变量,构造器,方法},每一个成分放大来看,他们都是对象;

反射的使用

1,获取类对象

/**
     * 1,获取类对象的 三种方式
     *
     * @throws ClassNotFoundException
     */
    private static void method1() throws ClassNotFoundException {
        //1, 类名.class
        Class<Monkey> monkeyClass = Monkey.class;
        //2,对象名.getClass();
        Monkey monkey = null;
        Class<? extends Monkey> aClass = monkey.getClass();
        //3,类的全路径 包名+类名 (常用)
        Class<?> aClass1 = Class.forName("com.edu.www.day0509.Monkey");
        Class<?> aClass2 = Class.forName("com.edu.www.day0509.Monkey");
        //一个类的类对象只有一个
        System.out.println(monkeyClass == aClass);
        System.out.println(aClass1 == aClass);
        System.out.println(aClass1 == aClass2);
    }

2,构造器的操作

  /**
     * 对构造器的操作
     *
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static void method3() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<?> aClass = Class.forName("com.edu.www.day0509.Monkey");
        //Constructor构造器类型
        // getConstructors只获取public修饰的构造器对象
        Constructor<?>[] constructors = aClass.getConstructors();
        System.out.println(constructors.length);
        // getDeclaredConstructors 获取本类声明的所有构造器对象
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        System.out.println(declaredConstructors.length);
        //getConstructor 只获取public修饰的某个构造器对象
        Constructor<?> constructor1 = aClass.getConstructor(String.class);
//        Constructor<?> constructor2 = aClass.getConstructor(int.class);
        Constructor<?> constructor3 = aClass.getConstructor(int.class, String.class);
        Object instance = constructor3.newInstance(11, "猴子3");
        System.out.println(instance);
        Constructor<?> constructor4 = aClass.getConstructor();
        //getDeclaredConstructor 所有修饰符的某个构造器对象
        Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class);
        //使用构造器创建对象 实例(对象 instance)
        Object o = declaredConstructor1.newInstance("猴子1");
        System.out.println(o);
        Constructor<?> declaredConstructor2 = aClass.getDeclaredConstructor(int.class);
        declaredConstructor2.setAccessible(true);
        Object o2 = declaredConstructor2.newInstance(12);
        System.out.println(o2);
    }

创建对象的简易方式

   /**
     * 创建对象简易方式
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private static void method4() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<?> aClass = Class.forName("com.edu.www.day0509.Monkey");
        //newInstance直接创建对象  其实是调用无参构造器对象去创建对象
        Object o = aClass.newInstance();
        System.out.println(o);
    }

3,对成员变量的操作

 /**
     * 对成员变量的操作
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws NoSuchFieldException
     */
    private static void method5() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<?> aClass = Class.forName("com.edu.www.day0509.Student");
        Object o = aClass.newInstance();
        System.out.println(o);
        //Field 成员变量类型
        //getFields只获取public修饰成员变量 也包含继承的
        Field[] fields = aClass.getFields();
        System.out.println(fields.length);
        // getDeclaredFields只获取本类声明的成员变量对象
        Field[] declaredFields = aClass.getDeclaredFields();
        System.out.println(declaredFields.length);
        // getField 只获取public修饰成员变量 也包含继承的
//        Field id = aClass.getField("id");
        // getDeclaredField  根据成员变量的名称 获取本类声明的某个成员变量对象
        Field declaredField1 = aClass.getDeclaredField("id");
        Field declaredField2 = aClass.getDeclaredField("name");
        declaredField1.setAccessible(true);
        declaredField2.setAccessible(true);
        //赋值的
        declaredField1.set(o, 1001);
        declaredField2.set(o, "张三");
        System.out.println(o);
    }

类的加载时机

  • 类是按需加载的,用到的时候才加载

  • 某个类只会被加载一次的

类加载器

  • 核心类加载器(启动类加载器) bootstrapClassLoader

    • 本地语言实现的

    • 核心包中核心类型

  • 扩展类加载器 platformClassLoder 平台类加载器

    • 扩展类

  • 应用类加载器 ApplicationClassLoader

    • 自定义的类型都是ACL加载

  • 其他类加载器

双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。

使用双亲委派模型的好处在于Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类,可以正常编译,但是永远无法被加载运行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值