`
jeffen2006
  • 浏览: 260541 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

利用java反射机制,子类从父类拷贝属性--解决信息修改类设计的模式

阅读更多

用例场景:在一个商户管理系统中,操作人员对一个已注册的商户进行修改,这就触发了一个商户修改的工作流,修改提交后,修改的商户信息和原商户信息会传递到审核人员的窗口进行审核,审核完毕后,新商户信息更新,同时旧商户信息去到历史库。

 

数据库:我们这里有三张表——BusiInfo,BusiInfo_hist,BusiInfo_ba。BusiInfo是商户信息表存放经过注册的商户信息;BusiInfo_hist是商户信息历史表,将修改完成后的商户原信息保存到此处;BusiInfo_ba是商户信息在途表,保存并未审核通过的修改后信息,当审核通过后转移到_hist历史表,并将在途信息删除。

 

例子:比如商户信息为a,现在修改为b,我们看看各表中的数据如何变化。

修改前 修改中 修改后
BusiInfo a a b
BusiInfo_ba b
BusiInfo_hist a

 

 

好,现在我们开始编码,我们采用的是hibernate,通常的做法是每个表对应一个javabean,当信息在不同表中进行转移的时候,通常的做法是将先一个javabean中的信息一个一个getMessage(),然后再一个一个setMessage()到另一个javabean中。如果属性很多的话这是一个体力活,同时如果以后有新增属性的话,还要回来维护这个传值的方法。

 

我们决定找到一个一劳永逸的方法来解决这类问题。这里我们用到了java继承和反射机制。

package com.mytesta;
/**
 * 商户信息类,父类
 */
public class BusiInfoIn {
	public String busiId;
	public String busiLoginname;
	public Long number;
	public Long getNumber() {
		return number;
	}
	public void setNumber(Long number) {
		this.number = number;
	}
	public String getBusiId() {
		return busiId;
	}
	public void setBusiId(String busiId) {
		this.busiId = busiId;
	}
	public String getBusiLoginname() {
		return busiLoginname;
	}
	public void setBusiLoginname(String busiLoginname) {
		this.busiLoginname = busiLoginname;
	}
}
package com.mytesta;
/**
 * 商户历史信息类,子类,同理可建立商户在途信息类
 *
 */
public class BusiInfoIn_his extends BusiInfoIn {
	public String deleteDate;

	public String getDeleteDate() {
		return deleteDate;
	}

	public void setDeleteDate(String deleteDate) {
		this.deleteDate = deleteDate;
	}
}
 
package com.mytesta;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import junit.framework.TestCase;

public class BusiInfoTest extends TestCase {
	 public void test() throws Exception {
		 //
		 BusiInfoIn_his busiInfoIn_his=new BusiInfoIn_his();
		 busiInfoIn_his.setBusiId("1243124");
		 busiInfoIn_his.setBusiLoginname("jeffen");
		 busiInfoIn_his.setDeleteDate("2009-1-1");
		 BusiInfoIn busiInfo =new BusiInfoIn();
		 busiInfo=(BusiInfoIn)busiInfoIn_his;
		 System.out.println("子类传父类=============================");
		 System.out.println(busiInfo.getBusiId());
		 System.out.println(busiInfo.getBusiLoginname());
		 
		 BusiInfoIn busiInfo2 =new BusiInfoIn();
		 busiInfo2.setBusiId("09090909");
		 busiInfo2.setBusiLoginname("runrun");
		 busiInfo2.setNumber(11L);
		 BusiInfoIn_his busiInfoIn_his2=new BusiInfoIn_his();
		 this.fatherToChild(busiInfo2, busiInfoIn_his2);
		 System.out.println("父类传子类=============================");
		 System.out.println(busiInfoIn_his2.getBusiId());
		 System.out.println(busiInfoIn_his2.getBusiLoginname());
		 System.out.println(busiInfoIn_his2.getNumber());
		 System.out.println(busiInfoIn_his2.getDeleteDate());
		 
		 
	 }
	 /*
	  * 将父类所有的属性COPY到子类中。
	  * 类定义中child一定要extends father;
	  * 而且child和father一定为严格javabean写法,属性为deleteDate,方法为getDeleteDate
	  */
	 private void fatherToChild (Object father,Object child)throws Exception{
		 if(!(child.getClass().getSuperclass()==father.getClass())){
			 throw new Exception("child不是father的子类");
		 }
		 Class fatherClass= father.getClass();
		 Field ff[]= fatherClass.getDeclaredFields();
		 for(int i=0;i<ff.length;i++){
			 Field f=ff[i];//取出每一个属性,如deleteDate
			 Class type=f.getType();
			 Method m=fatherClass.getMethod("get"+upperHeadChar(f.getName()));//方法getDeleteDate
			 Object obj=m.invoke(father);//取出属性值			 
			 f.set(child,obj);
		 }
	 }
	 /**
	  * 首字母大写,in:deleteDate,out:DeleteDate
	  */
	 private String upperHeadChar(String in){
		 String head=in.substring(0,1);
		 String out=head.toUpperCase()+in.substring(1,in.length());
		 return out;
	 }

}

 我们可以看到子类比父类多了一个属性deleteDate,代表进入历史表的时间。上面的运行结果如下

子类传父类=============================
1243124
jeffen
父类传子类=============================
09090909
runrun
11
null

 可以看到只要我们的持久类采用标准的javabean格式,子类从父类拷贝属性信息一步完成,而且不受以后属性增减的影响。

 

PS:想不到一个好的名字,先用这个标题吧。再过几天就春节了,忙里偷闲。

 

 

 

 

 

 
















 
2
0
分享到:
评论
2 楼 a4903039 2013-08-28  
higher141125 写道
高手,有个疑问,对于BusiInfoIn父类的属性修饰符为private,这会报错,如何解决?

高手已经给提示了“Class type=f.getType();  ”
部分代码稍微改动下,如下:
Method m2 = childClass.getMethod("set" + upperHeadChar(f.getName()),type);
m2.invoke(child, new Object[]{obj}) ;//设置子类值
1 楼 higher141125 2013-02-19  
高手,有个疑问,对于BusiInfoIn父类的属性修饰符为private,这会报错,如何解决?

相关推荐

    java全集.pdf JAVA全集

    - 反射允许程序在运行时获取类的信息并动态创建和操作对象。 #### 八、异常 **8.1 异常的基本概念** - 异常是在程序执行过程中发生的意外情况。 - Java使用异常处理机制来管理这些异常。 **8.2 捕获异常** - ...

    java笔记 java笔记

    ### Java基础知识概述 #### 1. 前言 Java是一种广泛使用的面向对象的编程语言,因其跨平台性、安全性和强大的功能而受到欢迎。...掌握这些核心概念和技术将有助于开发者更好地利用Java来解决问题。

    JAVA面试题汇总.pdf

    - 继承(Inheritance):子类自动拥有父类的属性和方法。 - 多态(Polymorphism):允许不同类的对象对同一消息做出响应,即方法的重载和重写,动态绑定技术实现。 2. 接口和抽象类的区别: - 接口是一种引用...

    传智播客Java_SE基础毕向东老师全程笔记

    - **继承**:子类继承父类属性和行为。 - **多态**:同一接口可以有不同的实现方式。 - 设计模式:如单例模式、工厂模式等。 ### 第四章:异常机制 - 异常处理机制:捕获、抛出、try-catch-finally语句。 - 自定义...

    CoreJava(java入门教程总结)

    - **反射**:在运行时获取类的信息并操纵对象的能力。 #### 10. 异常 - **概念**:用于处理程序运行时出现的错误。 - **捕获**:使用try-catch语句块捕获异常。 - **处理**:通过throw语句抛出异常,由调用者处理...

    Java入门学习笔记

    - **健壮性:** Java设计了许多机制来提高程序的健壮性和可靠性,如自动垃圾回收。 - **安全性:** Java具有严格的安全控制,可以在网络环境中安全地运行。 - **平台无关性:** Java编写的程序可以运行在任何支持...

    Core-Java-Interview-Questions.rar_core java interview

    - 继承的实现:子类继承父类的属性和方法。 - 多态的概念:单重继承与接口实现的多态性,以及如何实现动态绑定。 6. **接口** - 接口的定义和使用:接口的特性,如默认方法和静态方法。 - 实现多个接口:理解...

    JAVA核心技术

    - **父类(SuperClass)和子类(SubClass)的关系**:子类继承父类的属性和方法,并可以扩展新的功能。 ##### 7.3 多态(polymorphism) - **方法的覆盖(overridding)**:子类中定义一个与父类相同签名的方法。 - *...

    java面试100题,包含java基础等

    Java 中的访问修饰符、运算符、垃圾回收机制、自动装箱和自动拆箱、类加载机制、异常层次结构、接口和抽象类、内部类、深拷贝和浅拷贝、String、StringBuilder 和 StringBuffer、集合框架、泛型、反射、注解、并发...

    java面试笔记整理,包含java,redis,kafka等

    - **继承:** 允许子类继承父类的属性和方法。 - **多态:** 同一接口可以有多种不同的实现方式。 #### 八、面向对象编程的六大原则 - **单一职责原则(SRP):** 一个类只负责一项职责。 - **开放封闭原则(OCP):** 对...

    Java-JDK、数据库系统开发、Web开发学习笔记

    3. Java反射机制:反射机制允许程序在运行时透过Reflection API取得任何一个已知名称的class类的内部信息,包括其修饰符、父类类型、实现接口interface、属性字段、方法,并可以在运行时改变属性内容和调用方法。...

    java学习网址

    - **反射**:Java反射机制可以在运行时动态获取类的信息并直接操作。 #### JavaSE篇NO.33至NO.37:面向对象的高级特性 - **异常处理的深入理解**:包括自定义异常、异常链等高级话题。 - **Object类详解**:介绍了...

    Java基础面试题以及几个很有用的刷题网站.docx

    - **通过反射**:利用Class类或Constructor类的newInstance()方法创建对象。 - **使用clone方法**:实现Cloneable接口并通过clone()方法复制对象。 - **通过序列化**:通过反序列化过程创建对象。 #### 十三、...

    远光软件股份有限公司 最新复试题

    - 静态内部类:利用Java的类加载机制保证实例的唯一性。 - **饿汉式**:类加载时就创建实例,无需考虑线程安全问题。 - **登记式单例**:使用哈希表记录静态实例的存在状态,结合饿汉式的静态实例构建方法。 ###...

    java面试八股文java基础知识总结.pdf

    引用类型的值传递的是引用拷贝,修改对象会影响原对象状态。 #### Java包 - **JDK常用包**:如`java.lang`, `java.util`, `java.io`等。 - **`import java`与`javax`的区别**:`java`包通常是标准Java库的一部分,...

    SimpleJava.pdf

    ### SimpleJava知识点概览 #### 1. 从Java HelloWorld中能学到什么? - **程序结构**:HelloWorld示例通常包含一个`main`方法,它位于类内部,且类名与文件名相同。 - **基本语法**:了解如何... Java反射教程 - ...

    java学习笔记 初学者必读

    7.2.2. 父类(SuperClass)和 子类(SubClass)的关系 7-17 7.2.3. 系统构造一个对象的顺序 7-17 7.3. 多态(polymorphism) 7-18 7.3.1. 方法的覆盖(overridding) 7-18 7.3.2. 多态的分类 7-18 7.3.3. 运行时多态的...

    Java 208道面试.docx

    - 反射API允许在运行时检查类的信息,创建和操作对象,调用私有方法,甚至修改类的字段。 - Class类:代表Java类的运行时信息。 - 构造器、方法和字段的反射调用。 7. **对象拷贝** - 浅拷贝:仅复制对象的引用...

Global site tag (gtag.js) - Google Analytics