基于反射技术的高校体育测评系统优化实现研究
2021-10-23戈俊
戈 俊
1 研究目的
通过动态获取类中成员的Java反射技术,从而提高并优化高校体育测评系统的功能。
2 研究方法
2.1 文献资料法
根据研究内容和研究目的,查阅了近年来有关Java反射技术等方面的专著、期刊、论文和资料,并对资料进行整理分析、筛选、归纳、概括。为写作提供依据,为后续研究提供了充足的理论支持。
2.2 实验法
通过Eclipse集成开发软件,建立JavaSE开源项目,通过创建包、接口、类、配置文件等方法,进行项目开发的基本配置,通过WindowBuilder插件,进行GUI可视化组件开发,结合Java反射技术对已存在的NJFU_PECS高校体育成绩评测系统进行技术优化。
3 研究结果与分析
3.1 Java程序性能优化分析
前期为了满足教学与训练工作需求,已做好可以独立运行的应用程序NJFU_PECS高校体育成绩评测系统,可以正常安装并使用。用户在使用过程中需要提高该程序的扩展性,想加入一些自己所需的新功能。在程序开发初期,如果想添加新功能,其做法是定义一个类,并建立方法,通过new对象的方法,在主线程中调用该对象,并指挥对象调用功能方法即可。但是,现实生活中的应用程序是已经封装好的程序,是不可以随便将其源码进行改变同时建立对象的,又何况很多的程序开发时并非开源程序,是无法获取其程序源码的。因此,这种提高程序扩展性的想法是错误的。在这种情况下,程序需要提高扩展性,往往在设计初期会对外提供一个便于后期扩展使用的接口,程序设计厂商对外暴露接口规则,二次开发时通过实现该接口规则,第三方通过使用符合该接口规则的对象。这种操作方式可以形象的比作计算机对外提供的USB接口,通过该接口可以实现与外部设备的互联互通,如U盘、移动硬盘等。因此,对外提供接口只是为了进行功能扩展。
当需要进行功能扩展时,就应该针对接口的规则设计一个类,并通过该类实现接口,紧接着通过接口引用指向子类对象,以多态调用的形式即可使用扩展对象的方法。但是,回到原点还是之前的问题,如果无法在已写好的程序中更改其代码。那么,应该如何操作呢?新的思考方式是通过配置文件的方式,应用程序在启动时可通过流对象直接读取该配置文件,配置文件里配置的是即将使用到的扩展功能扩展类的类名,通过类名的读取,即可找到该类对应的class字节码文件。通过反射技术加载class字节码文件,并能成功获取该class字节码文件中的所有内容,通过类中的构造函数可以进行对象的创建,并且调用类中定义好的功能。如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,怎么可以实现?这就需要使用到反射技术。
3.2 Java程序基础调用与反射机制对比分析
3.2.1 Java反射技术的原理分析
JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法,即反向的映射类中的所有内容,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象方法的功能称为Java语言的反射机制,即动态获取类中信息,就是Java反射[1]。通过反射技术与配置文件相关联,运行配置文件中指定类的对应方法,读取配置文件中的数据,通过反射技术,来完成指定对象的创建[2]。只要在代码或配置文件中看到类的完整路径(包、类),其底层原理基本上使用的就是Java的反射机制。
3.2.2 获取任意类字节码文件对象的方法分析
第一种方法:Object类中有一个方法叫做getClass(),该方法必须明确被操作的类[3]。通过对象引用创建对象后,通过变量名称调用Object类中的可以被所有对象继承的getClass()方法,同时用描述字节码文件对象的类Class来接收该方法的返回值。
第二种方法:任何数据类型都具备一个静态的属性.class来获取其对应的Class对象[3]。该方法直接用类名.class的形式即可得到该数据的字节码文件对象,该方法的优点是简单,但还是要明确用到类中的静态成员,缺点是扩展性受限。
第三种方法:只要通过给定类的字符串名称就可以获取该类,描述字节码文件的类是Class,因此我们可以用Class类中的方法完成,Class类被定义在java.lang包内,此方法更为扩展[3]。该类中定义了一个静态方法forName(),该方法返回与带有给定字符串名的类或接口相关联的Class对象,该方法在定义时抛了一个ClassNotFoundException类未找到异常,因此值得注意的是该forName方法的参数字符串类名应该填写正确,并要求填写全类名即包名加类名。这种方式只要有类的名称即可,更为方便,扩展性更强。
3.2.3 常规创建对象和通过反射创建对象的区别
常规创建对象,通过包名加类名的方式,创建类所对应的实体对象,这样new对象后,就要在classpath路径内寻找名为包名加类名的字节码文件,并将其加载进内存,同时在堆内存中开辟一片空间。
通过反射创建对象,初期笔者手上只有字符串的类名,但是也想完成创建对象的动作。创建对象的基本原则是通过指定类名称,到指定位置找到字节码文件,加载进内存并在堆内存中开辟空间[4]。该步骤可通过Class.forName(“字符串包名+类名”)方法进行实现。反射机制作用下,获取其对象的方法是通过Class类中定义的方法newInstance()方法实现的,该方法可创建此Class对象所表示的类的一个新实例[4]。同时该实例返回值是Object,因为Object可接受任意对象。
两者创建实例的区别在于,传统创建需要程序员根据使用对象的不同,反复在程序中创建不同的对象,扩展性极弱,若对象众多,暂时无需使用到的对象也必须提前创建出来,极其浪费内存。而通过反射机制,可以将日后可能被使用到的对象类名写入配置文件中,需要用时让程序自身自动通过反射机制读取配置文件,逐个加载即可,提高扩展性的同时降低了内存的消耗。
3.3 高校体育评测系统反射设计思路与开发步骤分析
3.3.1 可视化界面设计思路分析
由于该系统的主要功能是提供用户进行高校体育成绩测试结果与评分的换算,因此开发前期首先要进行评测系统的GUI即可视化界面设计。按照普通设计思路,每一个测试项目的换算都需要独立设计一个测试类,也可以独立设计成一个测试换算系统,这样做的缺点是用户在同时录入多个测试项目时,需要频繁的启动并关闭不同的测评系统,浪费了大量的时间。而此系统在设计初期考虑到了使用反射机制来优化系统功能,因此在GUI界面设计时,可以通过设计下拉菜单的方式,灵活方便的转换体育评测项目,优势是不用关闭系统即可实现体育评测项目的切换,而该设计的技术基础就是使用Java的反射机制完成。
3.3.2 接口与实现类的设计思路分析
设计初期,由于该系统是保障数据换算结果的输出,那么此项目设计思路是首先定义一个测试接口,该接口中的抽象方法需要接受一个测试者测试项目的结果,由于不同项目的测试结果数据类型不同。如,50米跑、800米跑、立定跳远等测试结果数据类型均是浮点型;而仰卧起坐、引体向上等测试结果数据类型又都是整数类型,为了统一方便,笔者将该方法接收的参数类型均设计成双精度的浮点类型double。而该方法的转换测试必然会有一个结果,那么该方法的返回值类型也设计成双精度的double类型,该方法的方法名称就直截了当地设计成test,以便于体现方法的见名知意。
紧接着,需要设计每一个运动项目的测试类,他们的共性特点都是测试,因此都需要实现之前设计的接口,并覆盖掉接口中的抽象方法,只有覆盖掉接口中的抽象方法,并完成方法体中具体测试方法的设计,才能使用该方法。
3.3.3 配置文件的创建步骤分析
实现接口后的测试类定义完毕以后,笔者在该项目中创建一个配置文件test.properties,该配置文件的建立以便于后期通过反射机制找到该配置文件,并找寻配置文件中所需要运行的类文件的名称。下一步,将所有测试类的全类名即包名+类名通过键值对的形式写入配置文件。创建反射机制关联的配置文件test.properties如图一所示:
图一 创建反射机制关联的配置文件test.properties
3.3.4 反射机制的实现步骤分析
下面笔者就要开始进行反射机制的代码实现,首先需要通过缓冲字符输入流BufferedReader关联配置文件test.properties。通过循环读取,将配置文件中的所有键值对信息读取进来,通过字符串的切割方法将键值对通过“=”切成字符串数组,通过下拉菜单的选定测试项目类别与该字符串键值进行equals比对,如果比对成功,那么该键值对的值就是需要测试的项目类的类名,顺利获取该类名。流对象关联配置文件切割并校对键值对如图二所示:
图二 流对象关联配置文件切割并校对键值对
通过Class.forName()方法,将上述获取的类名作为参数传递给该方法,得到该类所对应的字节码文件对象。AccessibleObject类是Field字段、Method方法和Constructor构造方法对象的基类[5]。它提供了将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力[6]。通过该对象调用getMethod()方法,同时将测试方法名称“test “和该方法所需的参数类型的一个静态属性.class来获取其对应的Class对象,再通过之前字节码文件对象调用newInstance()方法,创建测试类实例对象,最后通过方法类的invoke()方法将对象实例和文本框中获取的测试数据传递给该方法参数,最后得到测试类转换的分值。再通过文本域将转换后的分值通过字符串表现在文本域中。反射机制完成对象建立并调用方法进行成绩换算如图三所示:
图三 反射机制完成对象建立并调用方法进行成绩换算
4 结论与建议
4.1 结论
前期开发的NJFU_PECS高校体育成绩评测系统过于臃肿,代码量过于冗长[7][8]。反射机制在本系统性能优化中使代码更加灵活,更加容易实现面向对象,大大地提高了程序的扩展性,实际优势表现为在不关闭系统前提下实现体育评测项目的切换;面向配置文件,降低了用户和开发者理解程序代码及执行流程的难度。
4.2 建议
为了提高程序的可扩展性,反射机制是程序开发的普遍设计趋势和方向;为了更具体的描述配置文件中的信息,后期可使用XML结构性的标记语言进行数据的描述与封装,再使用dom4j解析XML文档更利于维护。