getField 和 getDeclaredField 的区别

本文介绍了一种利用Java反射机制来复制两个具有相似属性的类之间的字段值的方法。通过演示如何获取并设置类的属性值,文章展示了如何将一个类实例的属性值复制到另一个类实例的过程。

   有这样一种场景,ClassA 与 ClassB 俩个类,这俩个类中的属性有很大一部分是相同的。比如:在使用MongoDB存储时,ClassA 

是商品信息,ClassB 是库存信息,ClassB的很多属性会和ClassA相同(原因:MongoDB关联查询性能会急速下降)。

这个时候已经创建好ClassA 类型的实例,需要创建ClassB类型的实例。

有如下俩种方式:

1、调用ClassB 每一个属性的set 方法。

2、通过反射设置;具体如下:

a> 获取ClassA  的所有属性名称

/**
	 * 获取所有属性
	 * @param instance
	 * @return
	 */
	public static String[] getAllTrributeNames(Object instance){
		Field[] fields = instance.getClass().getDeclaredFields();
		String[] attNames = new String[fields.length];
		for(int i  = 0; i < fields.length; i++){
			attNames[i] = fields[i].getName();
		}
		return attNames;
	}


b>循环属性,给ClassB  设置值

/**
	 * 获取属性值
	 * @param instance
	 * @param name
	 * @param value
	 */
	public static void setAttribute(Object instance, String name, Object value){
		try {
			Field field = instance.getClass().getDeclaredField(name);
			field.setAccessible(true);
			field.set(instance, value);
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 设置属性值
	 * @param instance
	 * @param name
	 * @return
	 */
	public static Object getAttribute(Object instance, String name){
		Object obj = null;
		Field field;
		try {
			field = instance.getClass().getDeclaredField(name);
			field.setAccessible(true);
			obj = field.get(instance);
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return obj;
	}


UserBean bean2 = (UserBean) getInstance(UserBean.class);
		System.out.println(bean2.toString());
		String[] attNames = getAllTrributeNames(bean1);
		for(String att : attNames){
			Object value  = getAttribute(bean1, att);
			setAttribute(bean2, att, value);
		}



但是在获取类的属性的时候,有俩个方法:getField 和 getDeclaredField。

看JDK源码,发现 getField 只获取 public 的属性,getDeclaredField 获取私有的属性 ;


俩个方法获取属性,都会调用 searchFields 方法,在getField 的时候,privateGetDeclaredFields会是false,但是getDeclaredField 是 true

    public Field getDeclaredField(String name)
        throws NoSuchFieldException, SecurityException {
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        Field field = searchFields(privateGetDeclaredFields(false), name);
        if (field == null) {
            throw new NoSuchFieldException(name);
        }
        return field;
    }

    public Field getField(String name)
        throws NoSuchFieldException, SecurityException {
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
        Field field = getField0(name);
        if (field == null) {
            throw new NoSuchFieldException(name);
        }
        return field;
    }

 private Field getField0(String name) throws NoSuchFieldException {
        // Note: the intent is that the search algorithm this routine
        // uses be equivalent to the ordering imposed by
        // privateGetPublicFields(). It fetches only the declared
        // public fields for each class, however, to reduce the number
        // of Field objects which have to be created for the common
        // case where the field being requested is declared in the
        // class which is being queried.
        Field res;
        // Search declared public fields
        if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) {
            return res;
        }







<think>嗯,用户问如何回退Git远程提交记录。我需要仔细思考这个问题,确保给出正确的步骤和注意事项。首先,用户可能已经将一些提交推送到远程仓库,但后来发现有问题,想要撤销这些提交。这时候,回退远程提交就需要用到Git的一些命令,比如git reset或者git revert,但要注意不同的方法有不同的影响。 首先,我应该考虑本地回退和强制推送到远程的情况。通常的做法是在本地回退到某个提交,然后使用git push --force来覆盖远程分支。但这样做有风险,尤其是当其他人也在同一个分支上工作时,可能会导致他们的提交丢失。需要提醒用户注意这一点。 接着,可能需要具体步骤。例如,用户需要先使用git log找到要回退到的提交的哈希值,然后用git reset --hard <commit-hash>来回退本地分支。之后,强制推送到远程仓库。但必须强调,只有在确定没有其他人依赖该分支的情况下才能这么做。 另外,git revert也是一个安全的选择,因为它会创建新的提交撤销之前的更改,而不会重写历史。这对于团队合作的项目更安全,因为不会影响其他人的工作流程。但用户的问题明确是回退远程提交,可能他们希望彻底删除某些提交,而不仅仅是撤销更改。 还有,可能需要提到其他相关命令,比如git push --force-with-lease,它比--force更安全,因为它会检查远程分支的当前状态是否与本地预期一致,避免覆盖其他人的提交。 还需要考虑分支保护的情况,比如在GitHub或GitLab上,默认分支可能被保护,不允许强制推送。这时候用户可能需要暂时解除保护,或者在临时分支上操作,然后通过合并请求来回退。 此外,提醒用户在操作前备份当前状态,比如创建一个临时分支,以防万一操作出错可以恢复。同时,强调在执行强制推送后,其他协作者需要同步他们的本地仓库,避免出现不一致的情况。 总结一下,回答的结构应该是先说明风险,再给出不同的方法(reset + force push,revert),比较它们的适用场景,然后分步骤说明操作流程,最后给出注意事项和建议。需要确保用户理解每种方法的后果,并根据实际情况选择合适的方式。</think>要回退Git远程提交记录,需谨慎操作以避免影响团队协作。以下是具体操作步骤及注意事项: --- ### 一、操作原理 Git远程提交记录本质是修改分支指针位置,通过本地回退后强制推送(force push)覆盖远程分支。⚠️ 此操作会重写历史记录,可能影响其他协作者。 --- ### 二、具体步骤 #### 方法1:使用 `git reset`(彻底删除提交) 1. **定位目标提交** ```bash git log --oneline # 找到要回退到的提交哈希值(如 abc123) ``` 2. **本地回退** ```bash git reset --hard abc123 # 将本地分支回退到目标提交 ``` 3. **强制推送到远程** ```bash git push --force origin 分支名 # 覆盖远程分支 # 更安全的替代命令: git push --force-with-lease origin 分支名 # 检查远程状态是否与本地预期一致 ``` #### 方法2:使用 `git revert`(安全撤销,保留历史) 1. **撤销指定提交** ```bash git revert 要撤销提交哈希值 # 生成一个反向提交 ``` 2. **推送新提交** ```bash git push origin 分支名 # 无需强制推送 ``` --- ### 三、关键对比 | 方法 | 适用场景 | 优点 | 缺点 | |------------|------------------------------|---------------------|-----------------------| | `git reset`| 个人分支/需要彻底
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值