花一杯茶的时间,学会Java反射(实用篇)

前言

之前,我写了一篇关于java反射的使用——花一杯茶的时间,学会Java反射(基础篇),今天就拿一些实例和应用给大家看看如何在项目中用反射。

实例

反射可以提高代码的扩展性,低耦合,高内聚。就拿工厂模式来说。

  1. 首先是简单工厂模式,没有使用反射。

     /**
      * 动物接口
      * 
      * @author chenjunxu
      * 
      */
     public interface IAnimal {
         /**
          * 品种
          */
         public void kind();
     }
    
     /**
      * 猫类
      * 
      * @author chenjunxu
      * 
      */
     public class Cat implements IAnimal {
    
         @Override
         public void kind() {
             System.out.println("I am cat!");
         }
    
     }
    
     /**
      * 狗类
      * 
      * @author chenjunxu
      * 
      */
     public class Dog implements IAnimal {
    
         @Override
         public void kind() {
             System.out.println("I am dog!");
         }
    
     }
    
     /**
      * 动物工厂类
      * 
      * @author chenjunxu
      * 
      */
     public class AnimalFactory {
    
         /**
          * 根据名称获取动物的实例
          * 
          * @param className
          * @return
          */
         public static IAnimal chooseAnimal(String className) {
             if (className.equalsIgnoreCase("Dog")) {
                 return new Dog();
             } else if (className.equalsIgnoreCase("Cat")) {
                 return new Cat();
             }
             return null;
         }
     }
    
     /**
      * 主类
      * 
      * @author chenjunxu
      * 
      */
     public class Main {
    
         public static void main(String[] args) {
             IAnimal animal = AnimalFactory.chooseAnimal("Cat");
             if (null != animal) {
                 animal.kind();
             } else {
                 System.out.println("没有此动物!");
             }
    
         }
     }
    

假设我们要新增一个动物:mouse。那么我们需要新建一个mouse类,然后在AnimalFactory工厂类中,加多一个if...else...的判断。假设需要添加十多个动物呢?大家也知道,if...else...用的越多,可能代码的可读性就越差,而且容易出错。
那么能不能每次添加一个新的动物类,然后不需要修改工厂类呢?答案就是反射。
接口IAnimal和类CatDogMain不改变,将工厂类修改成以下:

    /**
     * 动物工厂类
     * 
     * @author chenjunxu
     * 
     */
    public class AnimalFactory {
        
        /**
         * 根据动物类名获取动物的实例
         * 
         * @param className(包名+类名)
         * @return
         */
        public static IAnimal chooseAnimal(String className) {
            try {
                Class<?> clazz = Class.forName(className);
                return (IAnimal) clazz.newInstance();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

只要你的参数正确(记住是包名+类名),就可以获取到对应类的实例。

  1. 现在假设一种场景。有一个APP的通用框架,可以用来做多种多样的APP。现在,有一些APP需要分享功能,有一些不需要分享功能。那我们最好以插件的形式,将分享功能封装成jar包或者library。
    分享的jar包(分享库):

     package com.share.lib;
     /**
      * 分享库的分享类
      * 
      * @author chenjunxu
      * 
      */
     public class ShareLib {
    
         /**
          * 显示分享框
          * 
          * @param content
          */
         public static void showShareDialog(String content) {
             System.out.println(content);
         }
     }
    

工具类:调用分享库ShareLib的分享方法:

    package com.share.demo;

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    /**
     * 分享工具类
     * 
     * @author chenjunxu
     * 
     */
    public class ShareUtils {

        /**
         * 分享
         * 
         * @param content
         *            分享内容
         */
        public static void share(String content) {
            try {
                Class<?> clazz = Class.forName("com.share.lib.ShareLib");
                Method method = clazz.getMethod("showShareDialog", String.class);
                method.invoke(null, content);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

主方法调用工具类的分享方法:

    package com.share.demo;
    /**
     * 主类
     * 
     * @author chenjunxu
     * 
     */
    public class Main {

        public static void main(String[] args) {
            ShareUtils.share("我要分享内容!");
        }
    }

若是我们不需要使用分享功能,那就不需要修改工具类,直接不调用ShareUtils.share方法就行了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,833评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,478评论 18 399
  • 多态 任何域的访问操作都将有编译器解析,如果某个方法是静态的,它的行为就不具有多态性 java默认对象的销毁顺序与...
    yueyue_projects阅读 4,580评论 0 1
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 11,857评论 0 17
  • 丁酉年、正月初五。赏兰而归,有感:满目皆繁华、冬草犹余香。
    无声静候阅读 3,097评论 0 2

友情链接更多精彩内容