花一杯茶的時間,學會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方法就行了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 多態 任何域的訪問操作都將有編譯器解析,如果某個方法是靜態的,它的行為就不具有多態性 java默認對象的銷毀順序與...
    yueyue_projects閱讀 980評論 0 1
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,511評論 0 17
  • 丁酉年、正月初五。賞蘭而歸,有感:滿目皆繁華、冬草猶余香。
    無聲靜候閱讀 412評論 0 2