JAVA 反射修改static,final修飾的變量


  1. 調用對應Class的getDeclaredField或getField方法,獲取要修改的Filed;
    2個方法的差別在於:
    getDeclaredField可獲取當前Class內所有變量名(private,protect,public,friend),但不會獲取父類變量;
    getField可獲取當前Class及父Class內所有訪問級別為public的變量名;
  2. final修飾的常量不可修改,判斷field對應數據為常量則直接返回false;
    常量的判斷條件:
    1)使用了final修飾
    2)數據類型為基本類型或者String類型
    原因:
    使用final修飾后,被引用的數據地址將不可改變,我們只能嘗試修改地址上的內容,而常量不能修改地址內容,或者說修改不生效。
  3. 如果訪問級別不是public,調用setAccessible(true)獲得訪問權限;
  4. 如果使用了final修飾,而沒有使用static修飾,可以調用setAccessible(true)獲得修改權限,或者修改Modifier,去除final修飾符;
    如果同時使用了static和final,則只能通過修改Modifier去除final修飾符來獲取修改權限;
  5. 判斷要修改的數據類型,如果為基本類型,調用對應的基本類型修改方法,其他情況直接調用set方法;
  6. 對修改過的部分還原。

綜合上述步驟,對應代碼如下:

    public static boolean setValue(@Nullable Object source, @NonNull Class<?> target,
                                   @NonNull String name, @Nullable Object value) {
        Field field = null;
        int modify = 0;
        Field modifiersField = null;
        boolean removeFinal = false;
        try {
            field = target.getDeclaredField(name);
            modify = field.getModifiers();
            //final修飾的基本類型不可修改
            if (field.getType().isPrimitive() && Modifier.isFinal(modify)) {
                return false;
            }
            //獲取訪問權限
            if (!Modifier.isPublic(modify) || Modifier.isFinal(modify)) {
                field.setAccessible(true);
            }
            //static final同時修飾
            removeFinal = Modifier.isStatic(modify) && Modifier.isFinal(modify);
            if (removeFinal) {
                modifiersField = Field.class.getDeclaredField("modifiers");
                modifiersField.setAccessible(true);
                modifiersField.setInt(field, modify & ~Modifier.FINAL);
            }
            //按照類型調用設置方法
            if (value != null && field.getType().isPrimitive()) {
                if ("int".equals(field.getType().getName()) && value instanceof Number) {
                    field.setInt(source, ((Number) value).intValue());
                } else if ("boolean".equals(field.getType().getName()) && value instanceof Boolean) {
                    field.setBoolean(source, (Boolean) value);
                } else if ("byte".equals(field.getType().getName()) && value instanceof Byte) {
                    field.setByte(source, (Byte) value);
                } else if ("char".equals(field.getType().getName()) && value instanceof Character) {
                    field.setChar(source, (Character) value);
                } else if ("double".equals(field.getType().getName()) && value instanceof Number) {
                    field.setDouble(source, ((Number) value).doubleValue());
                } else if ("long".equals(field.getType().getName()) && value instanceof Number) {
                    field.setLong(source, ((Number) value).longValue());
                } else if ("float".equals(field.getType().getName()) && value instanceof Number) {
                    field.setFloat(source, ((Number) value).floatValue());
                } else if ("short".equals(field.getType().getName()) && value instanceof Number) {
                    field.setShort(source, ((Number) value).shortValue());
                } else {
                    return false;
                }
            } else {
                field.set(source, value);
            }
        } catch (Exception e) {
            return false;
        } finally {
            try {
                //權限還原
                if (field != null) {
                    if (removeFinal && modifiersField != null) {
                        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
                        modifiersField.setAccessible(false);
                    }
                    if (!Modifier.isPublic(modify) || Modifier.isFinal(modify)) {
                        field.setAccessible(false);
                    }
                }
            } catch (IllegalAccessException e) {
                //
            }
        }
        return true;
    }

2020-06-18


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM