Java基础-反射

反射(reflect)

  • Java程序的运行过程

    源文件(java)–》javac 编译器编译为class字节码文件–》类加载器加载到内存中(方法区中code segment)–》字节码校验器进行校验–》解释器进行解释–》操作系统执行

  • 被类加载器加载到内存的字节码文件其实就是一个又一个的Class(Filed,Mehtod,Constructor)的对象,把这些对象放大来看,里面的成员变量和方法都是对象

1.1.什么是反射

  • 动态的获取类的信息以及对类进行操作的机制;
  • 反射是框架的灵魂;
  • 目的:解耦,程序的可扩展性

1.2.反射的使用

1.获取Class类对象

常用的是Class.forName(“类的全路径名”);

public static void main(String[] args) throws ClassNotFoundException {
        // 1, 类名.class
        Class<Student> studentClass = Student.class;
        // 2, 对象.getClass()
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();
        // 3, Class.forName("类的全路径"); 包名+类名
        Class<?> aClass1 = Class.forName("com.qy28.sm.Student");
  }

2.获取class类对象的方法

public static void main(String[] args) throws ClassNotFoundException {
        // 3, Class.forName("类的全路径"); 包名+类名
        Class<?> aClass = Class.forName("com.qy28.sm.Student");

        //getMethods() 获取所有public的方法 包括继承下来的
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        //getDeclaredMethods获取本类中声明的方法(所有的),不包含继承的
        System.out.println("=============");
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());
        }
  }

3.获取class对象的成员变量

public static void main(String[] args) throws ClassNotFoundException {
        // 3, Class.forName("类的全路径"); 包名+类名
        Class<?> aClass = Class.forName("com.qy28.sm.Student");
        // getFields(); 获取所有public的成员变量 包括继承下来的
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        // getDeclaredFields() 获取本类中声明的成员变量(所有的),不包含继承的
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }
    }

4.获取构造器,如何获取指定的构造器

 public static void getConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // Class.forName("类的全路径"); 包名+类名
        Class<?> aClass = Class.forName("com.qy28.sm.Student");
        //获取构造器
        Constructor<?>[] constructors = aClass.getConstructors();
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName());
        }
        // 获取的是指定的无参的构造器
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        Object o = declaredConstructor.newInstance();
        System.out.println(o);
        //  获取的是指定的有参的构造器
        Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class);
        Object tom = declaredConstructor1.newInstance("anne");
        System.out.println(tom);
    }

5.获取指定的方法并进行调用, 重点掌握

 public static void getDeclaredMethod() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        // Class.forName("类的全路径"); 包名+类名
        Class<?> aClass = Class.forName("com.qy28.sm.Student");
        // 调用的是无参构造器
        Object o = aClass.newInstance();
        // 获取指定方法 无参
        Method declaredMethod = aClass.getDeclaredMethod("getName");
        // 通过反射进行方法调用
        declaredMethod.invoke(o);
        Method study = aClass.getDeclaredMethod("study", String.class, int.class);
        study.invoke(o, "abc", 12);
    }

6.反射的使用案例

public static void test() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 解耦
//        Student student = new Student("", new DellComputer());
        Class<?> aClass = Class.forName("com.qy28.sm.Student");
        // 获取学生构造器 Spring
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Computer.class);
        // 获取电脑的class类对象
        Class<?> aClass1 = Class.forName("com.qy28.sm.HuaComputer");
        // 获取电脑的指定构造器
        Constructor<?> declaredConstructor1 = aClass1.getDeclaredConstructor(String.class);
        // 实例化一个电脑实例
        Object computer = declaredConstructor1.newInstance("hua");
        // 实例化学生对象
        Object tom = declaredConstructor.newInstance("tom", computer);
        System.out.println(tom);
    }

1.3. 类的加载过程

1.动态的加载;按需加载,用的时候才会加载这个类的字节码文件

2.类加载器有哪些?

  • 核心加载器(bootstrap class loader)

    加载最核心的类;是本地语言写的,没有名字

  • 扩展类加载器

    加载的是jre/lib/ext包下面的类

  • 应用类加载器

    加载的是用户自定义的类

  • 其他加载器

3.双亲委派机制–防止字节码文件被重复加载

当类加载器收到一个加载类的请求的时候,会把请求先委派为父类,父类也会继续把请求往上委派,最终请求都会到达核心类加载器,如果在核心类加载器的加载范围就会去加载否则是加载失败继续往回追;如果父级都加载失败了才会由当前的类加载器进行加载

public static void main(String[] args) throws ClassNotFoundException {
      /*  Class<?> aClass = Class.forName("com.qy28.sm.load.A");//ClassNotFoundException
        System.out.println("=================");*/
       /* System.out.println(String.class.getClassLoader());
        System.out.println(AccessBridge.class.getClassLoader());
        System.out.println(LoadTest.class.getClassLoader());*/
        Class<LoadTest> loadTestClass1 = LoadTest.class; // AppClassLoder
        Class<LoadTest> loadTestClass2 = LoadTest.class; // ExtClassLoader
        Class<?> aClass = Class.forName("com.qy28.sm.load.LoadTest");
        LoadTest loadTest = new LoadTest();
//        AccessBridge.class.getClassLoader().loadClass("com.qy28.sm.load.LoadTest");
        System.out.println(loadTestClass1 == aClass);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值