JAVA中反射机制的研究

本文深入探讨了Java反射机制的概念、功能以及其实现方式,包括如何通过Class类实例化对象、获取接口、父类、构造函数和方法,并通过代码示例展示了反射机制在Java编程中的灵活运用。


    Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。

 

那么什么是Java的反射呢?

     JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
     Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

 

Class类

       要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。

 

       利用Java反射机制我们可以很灵活的对已经加载到Java虚拟机当中的类信息进行检测。当然这种检测在对运行的性能上会有些减弱,所以什么时候使用反射,就要靠业务的需求、大小,以及经验的积累来决定。


代码示例:

/*
* 内容 : Java的反射机制的学习
* 备注 :
* 	1、通过Class类的三种实例化对象
* 	2、通过class类中的newInstance()实例化对象
* 	3、获取所有接口
*	  	printAllInterfaces( myclass );
*		4、获得父类
*			printSuperClass( myclass );
*		5、获取所有的构造函数
*			printConstructors( myclass );
*		6、输出类中所有方法,包括父类的方法
*			printAllMethods( myclass );
*		7、输出类中所有属性,不包括父类的属性
*			printDeclaredFields( myclass );
*		8、通过反射调用函数
*			reflectInvoke( myclass );
*
* 作者 : UIT-ESPACE XXX
* 日期 :2012-10-28 
*/

// 编译时则为 javac -d . ReflectionDemo.java, 运行时要输入完整路径: java uit.demo.reflection.ReflectionDemo
package uit.demo.reflection;			

import java.util.*;
import java.lang.reflect.*;

// Person实现了Comparable的接口,可以排序
class Person implements Comparable<Person>{
	private String name;
	private int age;
	
	// 无参构造
	public Person(){
		
	}
	
	// 带参构造
	public Person(String name, int age){
		this.name = name;
		this.age = age;	
	}	
	
	// 设置名字
	public void setName(String name){
		this.name = name;
	
	}
	
	// 设置年龄
	public void setAge(int age){
		this.age = age;
	}
	
	// 获取名字
	public String getName(){
		return this.name;	
	}
	
	// 获取年龄
	public int getAge(){
		return this.age;	
	}
	
	// 转换成字符串
	public String toString(){
		return "姓名: " + this.name + ", 年龄: " + this.age;	
	}
	
	// 覆写equals函数,判断对象是否是同一对象
	public boolean equals(Object obj){
		if ( obj == this ){
			return  true;	
		}	
		
		if ( !(obj instanceof Person)){
			return false;	
		}
		
		Person per = (Person)obj;
		if ( per.name.equals(this.name) && per.age == this.age){
			return true;	
		}else{
			return false;	
		}
	}
	
	// 覆写hashCode(),hashCode表示对象的唯一编码
	public int hashCode(){
		return  this.name.hashCode() * this.age;	
	}
	
	// 排序接口的函数实现,使用此函数实现排序
	public int compareTo(Person per){
		if (this.age > per.age){
			return 1;
		}else if(this.age < per.age) {
			return -1;	
		}else {
			// 调用String中的compareTo()方法
			return this.name.compareTo(per.name) ;	
		}
	}
}

// main
public class ReflectionDemo{
	public static void main(String args[]) throws Exception{
		
		Person per = new Person();
		println("per的类为 : " + per.getClass().getName());
		
		// 三种方法实例化Class对象
		Class<?> c1 = null;
		Class<?> c2 = null;
		Class<?> c3 = null;
		
		// 1、最常用的方式是forName的形式
		c1 = Class.forName("uit.demo.reflection.Person");
		c2 = new Person().getClass();
		c3 = Person.class;
		
		println("per的类为 : " + c1.getName());
		println("per的类为 : " + c2.getName());
		println("per的类为 : " + c3.getName());
		
		// 2、通过反射机制实现对象的实例化,前提是自定义的类必须有无参构造函数
		Person per2 = (Person)c1.newInstance();
		per2.setName("反射");
		println(per2 + ",名字为: " + per2.getName() + "\n");
		
		// 3、通过获取构造方法,然后传参数的形式实例化对象
		Person per3 = null;
		// 获取所有的构造函数
		Constructor<?> con[] = c1.getConstructors();
		for ( Constructor<?> pers : con){
			println( "构造函数 : " + pers.toString() );	
		}
		println("\n");
		
		// 4、通过带参数的构造函数传参来实例化
		per3 = (Person)con[1].newInstance("某某人", 21);
		println( "通过反射机制和带参构造函数实例化: " + per3.toString() + "\n");
		
		
		// 5、获得类的所有结构,包括属性、方法、实现的接口、父类等
		getClassAll();
		
	}
	
	// 通过反射机制取得类的结构,包括属性、方法、接口、父类等
	public static void getClassAll() throws Exception{
		println("*****************************类的结构****************************");
		// 1、实例化Class对象
		Class<?> myclass = Class.forName("uit.demo.reflection.Person");

		// 2、获取所有接口
		printAllInterfaces( myclass );
		// 3、获得父类
		printSuperClass( myclass );
		// 4、获取所有的构造函数
		printConstructors( myclass );
		// 输出类中所有方法,包括父类的方法
		printAllMethods( myclass );
		// 输出类中所有属性,不包括父类的属性
		printDeclaredFields( myclass );
		// 通过反射调用函数
		reflectInvoke( myclass );
		
		println("*************************** FINAL END ******************************\n");
	}
	
	// 输出所有接口
	public static void printAllInterfaces( Class<?> myclass ){
		// 获取所有接口
		Class<?> iterfaceAll[] = myclass.getInterfaces();
		for ( Class<?> temp : iterfaceAll){
			println("实现了接口: " + temp);	
		}
	}
	
	// 输出父类
	public static void printSuperClass( Class<?> myclass ){
		// 获取父类
		Class<?> supercs = myclass.getSuperclass();
		println("父类: " + supercs + "\n");	
		
	}
	
	// 输出所有构造函数
	public static void printConstructors( Class<?> myclass ){
		// 获取所有构造函数
		Constructor<?> cons[] = myclass.getConstructors();
		for ( Constructor<?> pConstructor : cons){

			println( "构造函数 : " );
			// 获得修饰符,比如public 、private等
			int me = pConstructor.getModifiers();
			print(Modifier.toString( me ) + " ");	
			// 获得构造函数的名字
			print( pConstructor.getName() + "(");
			
			// 获取所有参数
			Class<?> params[] = pConstructor.getParameterTypes();
			for (int i=0; i<params.length; i++){
				print( params[i].getName() + " arg" + i);
				// 后面还有参数,则使用逗号分开
				if ( i < params.length - 1 ){
					print( ", " );	
				}
			}
			println( ")" );
			
		}
		println("\n");
		
	}
	
	// 输出所有类中定义的方法
	public static void printAllMethods( Class<?> myclass){
		
			println("***************类的所有方法,包括父类的方法****************");
			// getDeclaredMethods为得到本类中的所有方法,getMethods为获得所有方法,包括父类中的方法
			Method methods[] = myclass.getMethods();
			
			for (int i=0; i<methods.length; i++){
				// 获得返回值类型
				Class<?> returnType = methods[i].getReturnType();
				// 获得参数列表
				Class<?> params[] = methods[i].getParameterTypes();
				// 获得修饰符,public等
				int md = methods[i].getModifiers();
				
				// 1、输出修饰符
				print( Modifier.toString( md ) + " ");
				// 2、输出返回值类型
				print( returnType + " ");
				// 3、输出函数名
				print( methods[i].getName() + "(");
				// 4、挨个输出参数
				for(int j=0; j<params.length; j++){
					print( params[j].getName() + " arg" + j);
					if ( j < params.length -1 ){
						print( "," );
					}
				}
				print( ")" );
				
				// 获取抛出的异常名称
				Class<?> expt[] = methods[i].getExceptionTypes();
				// 如果含有异常参数则输出
				if (expt.length > 0){
					print( " throws " );
					for (int k=0; k<expt.length; k++){
						print( expt[k].getName());
						if ( k < expt.length - 1 ){
							print( "," );	
						}	
					}	
				}// end if
				print(";\n");
			} // end for		
			
			println("***************类的所有方法,包括父类的方法  END ****************\n\n");
	}
	
	// 输出类中的方法
	public static void printDeclaredFields(Class<?> myclass){
		
		println("********************类的属性*******************");
		// 获取类中的属性,不包括父类的属性
		Field decField[] = myclass.getDeclaredFields();	
		for (int i=0; i<decField.length; i++){
			// 获取修饰符
			String md = Modifier.toString( decField[i].getModifiers() );	
			// 属性的类型
			Class<?> type = decField[i].getType();
			print(md + " " + type.getName() + " " + decField[i].getName() + " ;\n");
		}
		println("********************类的属性*******************\n");
	}
	
	// 通过反射调用成员函数
	public static void reflectInvoke(Class<?> myclass) throws Exception{
		
		// 1、获得setName函数, 参数为String 类型的
		Method mt = myclass.getMethod( "setName", String.class);
		// 2、通过myclass.newInstance()构造对象
		Person per = (Person)myclass.newInstance();
		// 3、通过反射调用setName方法, 有参函数
		mt.invoke( per, "名字:反射调用");
		
		// 调用无参函数, 输出返回的信息
		Method mt2 = myclass.getMethod( "getName" );
		// 调用getName函数返回Person对象的名字
		String name = (String)mt2.invoke( per );
		print(  name + "\n");
		
	}
	
	// 输出信息
	public static void print(String msg){
		System.out.print( msg );	
	}
	
	// 输出信息,换行
	public static void println(String msg){
		System.out.println( msg );	
	}
}



### SAP中受托批指令流程订单受托外包装流程订单的区别 在SAP系统中,受托批指令流程订单(Subcontracting Batch Instruction Process Order)和受托外包装流程订单(Subcontracting Packaging Process Order)虽然都涉及外部协作方的参,但在实际业务场景中的应用目的、处理逻辑以及数据流存在显著差异。 #### 1. **定义应用场景** - **受托批指令流程订单** 主要用于生产制造过程中某一特定工序由外部供应商完成的情况。在这种模式下,企业将半成品发送至外部供应商处进行加工,供应商仅负责指定工序的操作[^3]。完成后,加工后的物品返回企业内部继续后续工艺直至最终成品入库。此类型的订单强调的是对外部供应商执行的具体加工作业及其费用核算。 - **受托外包装流程订单** 则专注于产品的包装环节外包给第三方服务商的情形。它通常发生在商品已经完成主要生产和组装之后,但需要额外的专业化包装服务才能满足市场或客户需求时采用的方式之一[^1]。这里更侧重于如何利用外部资源提升物流效率和服务质量而非单纯的技术性加工活动本身。 #### 2. **物料流动方向** - 对于**受托批指令流程订单**, 物料通常是未完全制成的产品部件或者中间状态下的材料被送往合作厂商那里接受进一步改造后再送回来加入到整体生产线当中去形成最终产物的一部分. - 而在**受托外包装流程订单**的情况下, 成品可能已经被制造完毕并准备就绪待运往客户手中之前才交给专门从事此类工作的单位来进行最后一步即适当形式(如按箱装载)以便运输储存更加便捷安全高效地到达目的地. #### 3. **财务管理重点** - 在涉及到成本计算方面,**受托批指令流程订单**更多关注的是基于所消耗时间长度或者其他衡量指标来确定应付予承包者的报酬金额大小等问题;同时还要考虑到原先转移出去那些处于初级形态阶段的商品价值变化情况等因素影响整个供应链的成本构分析过程之中. - 相较之下,**受托外包装流程订单**则把焦点放在因实施这些特殊安排所产生的附加支出上面——比如租赁使用某些专用设备设施之类的开销项目上,并且由于这属于末端处理性质的工作所以一般不会直接影响到核心产品本身的定价策略制定等方面考虑范围之内. #### 4. **系统配置功能支持** - 配合上述两种不同类型的任务需求,SAP软件平台提供了相应定制化的解决方案选项可供选择运用其中: - 当面对类似于前者那样的复杂技术要求较高的作业环境时候就需要启用更为精细复杂的参数设定机制以确保能够准确追踪记录每一个细节步骤进展状况直到顺利完成为止. ```abap CALL TRANSACTION 'CO01' USING itab MODE 'E' EXPORTING SELECTION-TABLE = sel_tab VARIANTS = var_tab[] ``` 上述代码片段展示了调用事务码`CO01`(创建生产订单)的一个例子,在设置条件筛选表(`sel_tab`)及变量列表(`var_tab[]`)的基础上自动化生成目标文档实例. - 至于后者相对简单明了一些的情境条件下,则可以通过简化版界面快速输入必要信息要素从而加快工作效率减少人为错误发生几率的同时保持足够的灵活性适应各种可能出现的变化情形. ```sql SELECT * FROM vbak INTO TABLE @DATA(lt_vbak) WHERE vbeln IN (@lv_belnr_low TO @lv_belnr_high). ``` 此SQL查询语句是从销售凭证头表(VBAK)提取符合条件的数据集存入局部内表@DATA(lt_vbak),适用于批量检索关联记录场合。 --- ### 论 综上所述可以看出尽管两者同属ERP领域内的子模块范畴却各自承担着截然不同的使命角色发挥独特作用贡献自身力量共同构建起现代化企业管理信息化体系大厦基石部分不可或缺的重要组成单元组成部分构成因素等等诸多层面意义非凡值得深入研究
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值