一、反射简介

之前讲的类加载:将类的类信息加载的JVM中,我们在运行时采用才可以使用这些类
前提的条件:JVM一定要知道它现在需要加载的是什么类
有一种情况:JVM在加载类的时候,它不知道该加载什么类,但是它在运行时, 却知道它现在需要什么类,此时就需要使用到反射机制,才可以解决它不知道的类
反射:在类加载时,不知道它要加载什么东西,但是在运行时,却知道了它需要用什么类,此时就反过头去重新加载的情况

举例说明

info.properties文件

  1. girl=com.woniuxy.java33.study.bean.GentleGirl
  1. package com.woniuxy.java33.study.bean;
  2. public class Girl {
  3. }
  1. package com.woniuxy.java33.study.bean;
  2. /**
  3. * 温柔型女孩
  4. * @author Administrator
  5. *
  6. */
  7. public class GentleGirl extends Girl{
  8. }
  1. package com.woniuxy.java33.study.bean;
  2. /**
  3. * 粗鲁型女孩
  4. * @author Administrator
  5. *
  6. */
  7. public class BlodGirl extends Girl{
  8. }
  1. package com.woniuxy.java33.study.util;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.util.Properties;
  6. /**
  7. * properties文件 的加载类
  8. * @author Administrator
  9. *
  10. */
  11. public class PropertiesUtil {
  12. public static String getValue(String key) {
  13. Properties props = new Properties();
  14. FileInputStream fis = null;
  15. try {
  16. String path = System.getProperty("user.dir") + File.separatorChar + "src" + File.separatorChar +"info.properties" ;
  17. File file = new File(path);
  18. fis = new FileInputStream(file);
  19. props.load(fis);
  20. }catch (Exception e) {
  21. // TODO: handle exception
  22. e.printStackTrace();
  23. }finally {
  24. try {
  25. fis.close();
  26. } catch (IOException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. }
  30. }
  31. return props.getProperty(key);
  32. }
  33. public static void main(String[] args) {
  34. System.out.println(getValue("girl"));
  35. }
  36. }
  1. package com.woniuxy.java33.study.reflect;
  2. import com.woniuxy.java33.study.util.PropertiesUtil;
  3. public class MainEnter {
  4. public static void main(String[] args) {
  5. // TODO Auto-generated method stub
  6. //妈妈安排相亲
  7. String girl = PropertiesUtil.getValue("girl");
  8. System.out.println(girl);
  9. // Girl girl =
  10. //用反射
  11. try {
  12. //forName() 调用 类加载器 去重新加载
  13. Class cls = Class.forName(girl);
  14. System.out.println(cls);
  15. System.out.println(cls.newInstance());
  16. } catch (Exception e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();
  19. }
  20. }
  21. }

反射中,最核心的方法:Class.forName()
该方法:Class.forName() 可以做到:在运行期去加载 需要的类

二、Class类

class类是反射中最重要的类
如果你在程序代码,需要使用到Class类,有3种方式获取:
1、Class.forName() 应用于反射
2、如果已知类的情况,使用类名.class 也可以获取到
3、如果已知类的对象,使用 对象.getClass() 同样可以获取到

三、如何使用Class 类来完成创建对象,调用方法,调用属性

3.1 创建对象

调用无参构造器,产生实例

  1. //forName() 调用 类加载器 去重新加载
  2. Class cls = Class.forName(girl);
  3. //根据cls创建实例 newInstance() 调用无参构造器
  4. Object obj = cls.newInstance();

调用有参构造器,产生实例

        //forName() 调用 类加载器 去重新加载
        Class cls = Class.forName(girl);
        //返回有参构造器
        Constructor cons = cls.getConstructor(String.class,Integer.class);
        Object obj = cons.newInstance("三上",18);
        System.out.println(obj);

3.2 调用属性

  //返回有参构造器
            Constructor cons = cls.getConstructor(String.class,Integer.class);
            Object obj = cons.newInstance("三上",18);
            System.out.println(obj);
//            //不能返回私有属性
//            Field field = cls.getField("girlName");
//            System.out.println(field.get(obj));
            //可以返回 私有属性
            Field field = cls.getDeclaredField("girlName");
            //给其他类,授权访问 私有属性
            field.setAccessible(true);
            System.out.println(field.get(obj));
            //set 主要给属性赋新的值
            field.set(obj, "市川**");
            //get 主要用于获得属性的内容
            System.out.println(field.get(obj));

3.3 调用方法

 //获取私有方法
            Method meth = cls.getDeclaredMethod("cry", null);
            meth.setAccessible(true);//同样给私有方法,授权
            System.out.println(meth);
            //调用方法(第一个参数表示对象,第二个参数表示 具体的值)
            Object result = meth.invoke(obj, null);
            //输出方法的返回结果
            System.out.println(result);
            //获得非私有方法(第一个参数表示方法名,第二个参数表示 参数类型)
//            Method meth = cls.getMethod("cry", null);
//            System.out.println(meth);
//            //调用方法(第一个参数表示对象,第二个参数表示 具体的值)
//            Object result = meth.invoke(obj, null);
//            //输出方法的返回结果
//            System.out.println(result);

3.4 获得注解

  //返回有参构造器
            Constructor cons = cls.getConstructor(String.class,Integer.class);
            Object obj = cons.newInstance("三上",18);
            System.out.println(obj);
            //根据方法对象,获得方法上的 注解
            Method meth = cls.getMethod("cry", null);
            MyLog mylog = meth.getAnnotation(MyLog.class);
            System.out.println(mylog.menuName());
            System.out.println(mylog.optType());