java反射

反射

首次接触反射之后对反射的理解是:反射是框架底层的实现,通过动态加载类,然后动态创建对象,然后调用方法去实现。(…脑子空白)


Java提供的API,其功能是动态的加载类,动态创建对象,动态调用对象,动态访问属相等


系统的学习反射

1.学习反射时搞清楚如下概念

(1.)静态
-静态:约定执行流程,在运行期间按照固定规则进行
-案例:

Foo foo = new Foo();
String s = foo.hello();
System.out.println(s);
//说明:编译以后,按照时间按照固定规则及执行

(2.)动态
-动态:在运行期间动态加载类,动态创建对象,动态执行方法。
-案列:执行一个类中的全部以test为开头的方法
-说明:在程序运行之前不知道类名,方法名。

2.反射API(API参照Jdk7文档)

(1.)功能

  • 动态加载类
    • 语法: Class cls = Class.forName(类名)(图片未上传)
  • 动态创建对象
    • 前提:程序执行之前之前不知道类名,在运行期间动态获取类名,动态加载类并且创建对象。
    • 语法:Object obj = cls.newInstance();
    • 注意:动态调用对象的无参构造器,被调用的类必须有无参构造器,如果没有将抛出异常(如:扩展流java.io.BufferedInputStream,高级流等;将抛出java.lang.InstantiationException和java.lang.NoSuchMethodException异常),反射API也提供了调用有参构造器额方法,但是不常用。
  • 动态执行方法

    • 找到方法信息

      • 语法1. Method[] methods = cls.getDeclaredMethods();
      • 说明:返回一个类的全部信息,只包含当前类的方法信息,返回值得数组,每个元素代表一个方法详细信息。


      • 语法2. Method[] methods = cls.getMothods();

      • 说明:找到全部共有方法信息想(含继承方法)


      • 语法3. Method method = cls.getDeclaredMethod(方法名,参数类型列表);

      • 说明:找到一个特定的方法信息,里面包含参数(根据方法的签名找到一个方法),参数类型列表是Class数组对象,如:Class[] types = {int.class,String.clss};

    以上方法详细信息: Method对象包含全部的方法信息。


    • 执行方法
    • 语法:Object obj = method.invoke(对象,传递的参数…);
    • 说明: invoke调用,执行一个方法。
    • 注意:对象和method必须是相关的,对象的类型上一定存在指定的方法,如果没有就会抛出异常,参数必须匹配,如果不匹配也会出现异常。
    • 例子:
      /**
      * 执行某个类中全部以age为开头的方法
      * 都是非静态方法
      * 方法都是无参数无返回值的方法
      * 类有无参数构造器
      * @author soft01
      */
      - public static void main(String[] args)throws Exception {
          Scanner in = new Scanner(System.in);
          System.out.println("请输入类名:");
          String className = in.nextLine();
          //动态加载类
          Class cls = Class.forName(className);
          //动态查找方法
          Method[] methods = cls.getDeclaredMethods();
          //遍历每个方法,查找方法名是以age为开头的
          Object obj = cls.newInstance();
          for(Method method:methods){
              String name = method.getName();
              //获取方法的参数类型列表
              Class[] types = method.getParameterTypes();//获取参数类型列表
              System.out.println(name+":"+Arrays.toString(types));
              //检查参数类型列表长度
              if(types.length!=0){
                  continue;
              }
      
              if(name.startsWith("age")){
                  System.out.println(name+":");
                  //string API 
                  //找到了test开头的方法
                  method.invoke(obj);//传递的参数...
              }
          }
      }

  • 动态访问属性

    • 语法1. Field[] fields = cls.getDeclaredFields();
    • 说明:显示一个类的所有属性。


    • 语法2. Field field = cls.getDeclaredField(属性名(name));

    • 例子:
        package cn.tedu.demo;

        import java.lang.reflect.Field;
        import java.util.Scanner;

        /**
         * 动态读写属性
         * @author soft01
         *
         */
        public class Demo6 {

            public static void main(String[] args)throws Exception {
                Scanner in = new Scanner(System.in);
                System.out.println("输入类名: ");
                String className = in.nextLine();
                //动态加载类
                Class cls = Class.forName(className);
                //动态获取属性信息
                System.out.println("属性名陈: ");
                String name =  in.nextLine();
                //查找属性 : 在方法区中的类信息里查找属性信息
                Field field = cls.getDeclaredField(name);
                //读取属性
                // obj 参数是包含属性值的对象
                Object obj = cls.newInstance();
                field.setAccessible(true);//私有属性,或者方法(method)就可以访问喽 打破了封装
                //field.set(obj, "meimei");
                field.set(obj, 100);
                Object val = field.get(obj);
                System.out.println(val);
            }

        }
  // 其中:field.setAccessible(true);用于打开不可见属性的访问权限,可以打破封装访问不可以见属性。

何时使用反射

当设计一个操作,在操作时候不知道类名,方法名,属性;反之,尽量不要使用反射,反射性能“稍慢”。

实现Junit4原型

  • 业务需求:动态执行一个类中全部使用@Test标记的方法
  • 分析:不知道类名,不知道方法名,必须使用反射。
  • 注意: 创建的注解@annotation类时加上传播机制注解(@Retention(RetentionPolicy.SOURCE))
  • 例子:
    import java.lang.reflect.Method;
    import java.util.Scanner;
    public static void main(String[] args) throws Exception {
    Scannner scan = new Scanner(System.in);
    System.out.println("请输入类名");
    String className = scan.nextLine();
    Class cls = Class.forName(className);
    Object obj = cls.newInstance();
    Method[] methods = cls.getDeclaredMethods();
    for(Method method : methods){
        /*
        * 查找注解
        * 查找方法是否有@Test注解,有则返回注解类型对象
        * 如果没有则返回null
        */
        Test annotation = method.getAnnotation(Test.class);
        //注意Test注解接口 一定要加上传播机制注解
        System.out.println(annotation);
        //如果是私有方法,需加上如下代码
        //method.setAccessible(true);
        if(annotation != null){
        //* 根据业务需求如果是要做测试就执行此方法。
        //* 如果是注入 就添加属性 设置值。
            method.invoke(obj);//完成了动态执行@Test方法
        }
    }
}

//注解是如果工作的,原理是什么:在 运 行 期 间利用反射API解析并且处理注解。
    图略

模仿Spring 读取配置配置文件

模仿Spring 读取配置配置文件

//需要引用dom4j的jar包
public class ApplicationContext{
    private Map<String,Object> beans;
    public ApplicationContext(String xml){
            beans = new HashMap<String,Object>();
            //高级流依赖低级流
            SaxReader reader = new SaxReader();
            //读取报下的xml文件 也可以是照片等
            InputStream in = this.getClass().getLoader().getResourceAsStream(xml);
            Document doc = reader.read(in);
            //获取根节点<beans> 子元素<bean id="" class=""> 
             Element root = doc.getRootElement();
             //获取全部子元素bean
             List<Element> list = root.ellments();
             //遍历每个bean,为每个bean创建一个对象
             for(Element bean:list){
                 //获取bean的 id class属性
                  String id= bean.attributeValue("id");
                  String className = bean.attributeValue("class");
                //利用反射API创建对象
                Class cls = Class.forName(className);
                Object obj = cls.newInstance();
                //缓存到map对象中
                beans.put(id,Obj);
                }

    }
    public getBean(String id){
        //根据key的值找到对应的value 通过map对象
        return beans.getBean(id);
    }   
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值