Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 362|回复: 0

[Java反射学习]Java程序的动态扩展

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-28 23:56:25 | 显示全部楼层 |阅读模式
    这里所谓的可扩展应用,是指这样的编程语言或者系统,它可以在不修改现有系统整体或任意一部分功能的情况下,扩展自身的功能。

         对于传统的编程语言,比如Cobol、C、C++,如果要为它们的应用增加新功能,程序员必须重新编辑、编译和发布程序,因为这些语言都是静态链接的语言,不具备动态添加功能的机制(也就是说,生成执行代码的时候,所有的程序代码必须事先准备妥当)。java应用的可扩展能力突破了这些限制。

    Java应用的可扩展功能包含了允许动态地定义新的数据类型以及允许用户插入自己的程序例程的能力。这一切是如何实现的呢?下面我们通过实例来了解具体的实现过程。

    普通应用的扩展
    在Java中,扩展性源于继承,具体手段或者是扩展一个类,或者是实现一个接口。Java接口的主要用途就在于此。(Java接口定义了一组方法,但不包含实现。实现某个接口的类必须实现该接口定义的所有方法,因而也就遵循某种确定的行为模式。)   
      
       
       
         
       

         
       
      
         为什么说这个功能对于普通程序来说也很重要呢?如果一个程序是可以动态扩展的,用户就不必再为了添加新功能而去修改源程序。这就避免了搞乱原有的代码,使得用户能够专注于自己的那一部分代码。此外,程序不必为了引入新功能而重新启动,这对于那些需要不间断运行的程序来说无疑是一个福音。

    为进一步了解Java程序的动态扩展技术,我们来看一个例子。一家快速增长的保险公司想要用计算机管理它的报价系统。这家公司现有两个产品:人寿保险(lifecare)和医疗保险(medicare)。根据保额、期限、客户年龄和保险产品的不同,月保险费用的计算方法也不同。系统应该能够在不修改原有代码的情况下,引入保险公司推出的其他产品。为现有产品设计的类模型如图一所示。


        当一个客户试图获取某种保险产品的报价时,系统创建一个对应该产品类型的对象,调用该对象的calculatePremium()方法,根据指定产品的计算方法计算出保险费用。系统利用一个XML文件(或属性文件)描述现有产品信息,比如保险产品的名称和相应的类名称。XML文件如Listing 1所示。



        系统从XML文件读取指定产品的类的全称,动态地创建对象。然后,系统调用calculatePremium(),根据指定的保额、期限和客户年龄,按照特定产品的计算逻辑计算出精确的保险费。

    现在我们来看看系统如何动态地装入对象。在把类装入内存和创建特定产品类型的对象时,系统用到了Java类库java.lang.Class。Class类的实例或者代表着Java应用中的一个类,或者代表着一个接口。在后台,Java虚拟机(JVM)常常利用Class类操作Java类;然而,用户程序也同样可以通过Class类的实例操作Java类。请参见Listing 2的Class类摘要。

    1. 【Listing 2:Class类概要】
    2.   
    3.  public final class java.lang.Class extends java.lang.Object
    4.   {
    5.     public static Class forName(String className)
    6.     public static Class forName(String name, boolean initialize, ClassLoader loader)
    7.     public Class[] getClasses()
    8.     public ClassLoader getClassLoader()
    9.     public Class getComponentType()
    10.     public Constructor getConstructor(Class[] parameterTypes)
    11.     public Constructor[] getConstructors()
    12.     public Class[] getDeclaredClasses()
    13.     public Constructor getDeclaredConstructor(
    14.     Class[] parameterTypes)
    15.     public Constructor[] getDeclaredConstructors()
    16.     public Field getDeclaredField(String name)
    17.     public Field[] getDeclaredFields()
    18.     public Method getDeclaredMethod(String name, Class[],parameterTypes)
    19.     public Method[] getDeclaredMethods()
    20.     public Class getDeclaringClass()
    21.     public Field getField(String name)
    22.     public Field[] getFields()
    23.     public Class[] getInterfaces()
    24.     public Method getMethod(
    25.     String name, Class[] parameterTypes)
    26.     public Method[] getMethods()
    27.     public int getModifiers()
    28.     public String getName()
    29.     public Package getPackage()
    30.     public ProtectionDomain getProtectionDomain()
    31.     public URL getResource(String name)
    32.     public InputStream getResourceAsStream(String name)
    33.     public Object[] getSigners()
    34.     public Class getSuperclass()
    35.     public boolean isArray()
    36.     public boolean isAssignableFrom(Class cls)
    37.     public boolean isInstance(Object obj)
    38.     public boolean isInterface()
    39.     public boolean isPrimitive()
    40.     public Object newInstance()
    41.     public String toString()
    42.   }
    复制代码
       在这里,我们感兴趣的主要是forName()方法和newInstance()方法。

         静态方法forName()返回和指定类名字关联的Class对象。它通过类装入器把类装入到执行程序。类名字参数可以是classpath中存在的任意一个类。如果不能找到指定类,则forName()方法抛出ClassNotFoundException异常。

          newInstance()方法为Class对象代表的类新建一个实例。newInstance()方法也利用类的不带参数的构造函数创建新对象,因此该类必须有一个不带参数的构造函数。如果newInstance()方法由于任何原因不能实例化一个类,它将抛出InstantiationException异常;如果不能访问该类或它的构造函数,则抛出IllegalAccessException异常。
    Listing 3显示了Product接口和它的实现:MediCare,LifeCare。

    【Listing 3:Product接口及其实现】

    1. // Product.java
    2. // Product接口
    3.   
    4. package com.test.dynamic;
    5. public interface Product
    6. {
    7.  public float calculatePremium(float face-value,int term, int age);
    8.  }
    9.   
    10.   
    11. // MediCare.java
    12. // Product的一个实现
    13. package com.test.dynamic;
    14. public class MediCare implements Product
    15. {
    16.  public float calculatePremium(float face-value, int term , int age)
    17.  {
    18.   
    19.   float premium;
    20.   // 计算保险费
    21.   // ......
    22.   return premium;
    23.  }
    24. }
    25.   
    26.   
    27. // LifeCare.java
    28. // Product的一个实现
    29. package com.test.dynamic;
    30. public class LifeCare implements Product
    31. {
    32.   public float calculatePremium(float face-value, int term , int age)
    33.   {
    34.     float premium;
    35.     // 计算保险费(不同的保险产品,计算方法不同)
    36.     // .......
    37.     return premium;
    38.   }
    39. }
    复制代码
        当用户询问报价时,报价系统根据保险产品的名字装入并实例化产品类。下面我们用两个方法实现装入和调用代码。

    GetProductFromName根据指定的产品名字生成合适的产品对象,makeQuote()方法计算保险费。

    Listing 4显示了它们的代码:

    1. 【Listing 4:生成产品对象,计算保险费】
    2.   
    3. public Object GetProductFromName(String productName)
    4. {
    5.   // 待装入对象的类名称
    6.   String className = null;
    7.   // 利用XML分析库org.xml.sax,
    8.   // 从XML文件获取产品的相应类名称
    9.   // ......
    10.  
    11.   // 假定类名字对应正确的产品,例如
    12.   // "Com.test.dynamic.MediCare"
    13.   try
    14.   {
    15.    Object o = null;
    16.    o = Class.forName(className).newInstance();
    17.   }
    18.    //catch(ClassNotFoundException e){}
    19.    //catch(InstantiationException e){}
    20.    //catch(IllegalAccessException e){}
    21.   catch( Exception e )
    22.   {
    23.     e.printStackTrace();
    24.   }
    25.   
    26.   return o;
    27.   
    28.   }
    29.   
    30.   // makeQuote方法无返回值
    31.   
    32.   public void makeQuote()
    33.    {
    34.     String productName;
    35.     float faceValue , premium ;
    36.     int faceValue, age;
    37.     // 从应用的用户界面获取所有参数,包括
    38.     // 产品名称、期限、保额、年龄
    39.      ....
    40.      }
    41.    略。
    复制代码


      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 02:32 , Processed in 0.364832 second(s), 36 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表