直接上代码- package com.itcast.test2;
- import java.lang.reflect.*;
- import com.itcast.test1.Ball;
- public class RuntimeClone {
- /**
- * 运行时复制对象
- * 这个方法能够创建一个和参数 object 同样类型的对象,
- * 然后把 object 对象中的所有属性拷贝到新建的对象中,
- * 并将它返回 ,这个例子只能复制简单的 JavaBean
- * @author shandawang
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Ball ball = new Ball("basketball",1);
- try {
- Ball cloneBall = (Ball)runtimeClone(ball);
- System.out.println(cloneBall.toString());
- } catch(Exception e) {
- e.printStackTrace();
- }
- }
- /**
- *
- * @param obj 要复制的对象
- * @param args 构造函数参数列表
- * @return 复制后的对象
- */
- public static Object runtimeClone(Object obj) throws Exception {
- // 获取对象的完整类型
- Class<?> classType = obj.getClass();
- //System.out.println(classType.getName());
- // 使用默认构造方法创建一个实例
- /*
- * 注意:若Ball类型定义了带参数的构造函数,则JVM不会定义默认构造函数
- * 此时必须自定义不带参数的构造函数
- */
- Object cloneObj = classType.getConstructor().newInstance();
- // 获取被复制对象的所有属性
- Field[] fields = classType.getDeclaredFields();
- String[] fieldNames = new String[fields.length]; // 属性名数组
- for(int i = 0;i < fields.length;i++) {
- // 获取属性名,通过反射调用对象的getters,setters
- fields[i].setAccessible(true);
- fieldNames[i] = fields[i].getName();
- // 属性名的首字母大写,获取方法名
- String firstUpperCaseLetter = fieldNames[i].substring(0, 1).toUpperCase();
- String getterMethodName = "get" + firstUpperCaseLetter +
- fieldNames[i].substring(1,fieldNames[i].length()); // get方法名
- //System.out.println(getterMethodName);
- String setterMethodName = "set" + firstUpperCaseLetter +
- fieldNames[i].substring(1,fieldNames[i].length()); // set方法名
- //System.out.println(setterMethodName);
- Method getterMethod = classType.getMethod(getterMethodName);
- Method setterMethod = classType.getMethod(setterMethodName,fields[i].getType());
- // 调用原对象的get方法获取指定属性值
- Object fieldValue = getterMethod.invoke(obj);
- // 调用复制对象的set方法设定指定属性值
- setterMethod.invoke(cloneObj,fieldValue);
- }
- return cloneObj;
- }
- }
复制代码- package com.itcast.test1;
- import java.io.Serializable;
- /**
- * javabean多用于封装属性,而很少具备某些特定的方法功能。
- * 试想,javabean的功能就是传递数据,那么类权限为共有也
- * 就不足为奇了。下面是标准javabean要遵守的一些规范:
- *1. 类访问权限为公有
- *2. 所有属性为私有
- *3. 每个字段对外提供setter方法和getter方法
- *4. 具备一个无参的构造方法
- */
- public class Ball implements Serializable {
- //private static final long serialVersionUID = 1L;
- /**
- * 实现序列化
- * 要将某类的对象序列化,则该类必须实现Serializable接口,该接口
- * 仅是一个标志,告诉JVM该类的对象可以被序列化。如果某类未实现Serializable接口,
- * 则该类对象不能实现序列化。
- */
- private String ballName;
- private int serialNumber;
- public Ball() {}
- public Ball(String ballName, int serialNumber) {
- super();
- this.ballName = ballName;
- this.serialNumber = serialNumber;
- }
- public String getBallName() {
- return ballName;
- }
- public void setBallName(String ballName) {
- this.ballName = ballName;
- }
- public int getSerialNumber() {
- return serialNumber;
- }
- public void setSerialNumber(int serialNumber) {
- this.serialNumber = serialNumber;
- }
- @Override
- public String toString() {
- return "Ball [ballName=" + ballName + ", serialNumber=" + serialNumber
- + "]";
- }
- }
复制代码 Ball类是之前序列化和反序列化时实现了serializable接口。现在我要运行时通过反射复制对象,而ball对象里有序列化ID号,获取属性时同时也会获得这个属性。而这不是我希望的(程序不能运行)。当所有属性都是private时,能不能跳过这个序列号属性。 |