篡改Java final参数

来源:互联网 发布:淘宝813大促 编辑:程序博客网 时间:2024/05/22 03:50

       在Java语法里, final关键字用在声明参数时, 该参数叫做常量; 否则叫做变量。 

       final关键字的作用是值(或引用)不可改, 但引用的对象可以改值。

常量的一般声明方式:

    class SomeClass {        final int SOME_CONSTANT1 = 1;        final int SOME_CONSTANT2 = 2;                ......    }
        声明时为final参数赋初值, 这种情况下不能篡改。
      但是声明final参数时不赋初值, 这种情况下是可以篡改的!!! 例如: final int a; a = 1;   可以通过反射修改参数a的值。

      为什么使用关键字后参数就是常量, 不能修改了呢???

  其实final属性以及访问权限都对应一个二进制比特位, 在java.lang.reflect.Modifier.java里声明:

public class Modifier { /**     * The {@code int} value representing the {@code private}     * modifier.     */    public static final int PRIVATE          = 0x00000002;    /**     * The {@code int} value representing the {@code protected}     * modifier.     */    public static final int PROTECTED        = 0x00000004;    /**     * The {@code int} value representing the {@code static}     * modifier.     */    public static final int STATIC           = 0x00000008;    /**     * The {@code int} value representing the {@code final}     * modifier.     */    public static final int FINAL            = 0x00000010;.......}
        那么是否可以篡改函数、属性的访问特性呢? 答案是肯定的。 下面以修改final属性为例:


  static class Test {        private final int a;  //赋值后仍然可以该        private int b;        private final int c = 3;    //改不了        Test(int param1, int param2) {            a = param1;            b = param2;        }        public int getValueA() {            return a;        }        public int getValueB() {            return b;        }        public int getValueC() { return c; }    }    /**     * 清除final属性, 及修改modifier参数     * @param field     */    public static void removeFieldFinalModifier(final Field field) {        if (field == null) {            return;        }        try {            if (Modifier.isFinal(field.getModifiers())) {                final Field modifiersField = Field.class.getDeclaredField("modifiers");                final boolean doForceAccess = !modifiersField.isAccessible();                if (doForceAccess) {                    modifiersField.setAccessible(true);                }                try {                    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);                } finally {                    if (doForceAccess) {                        modifiersField.setAccessible(false);                    }                }            }        } catch (final NoSuchFieldException ignored) {            // The field class contains always a modifiers field        } catch (final IllegalAccessException ignored) {            // The modifiers field is made accessible        }    }    public static void main(String[] args) {        Test obj = new Test(1, 2);   //a等于1, b等于2        Class clz = Test.class;        System.out.println("final属性a篡改前:" + obj.getValueA());        System.out.println("非final属性b篡改前:" + obj.getValueB());        System.out.println("final属性c篡改前:" + obj.getValueC());        try {            Field fieldA = clz.getDeclaredField("a");            fieldA.setAccessible(true);            Field fieldB = clz.getDeclaredField("b");            fieldB.setAccessible(true);            Field fieldC = clz.getDeclaredField("c");            fieldC.setAccessible(true);            removeFieldFinalModifier(fieldA);   //删除final限制            fieldA.setInt(obj, 11);  //final属性a的值从1变为11            fieldB.setInt(obj, 22);    //值变为22            removeFieldFinalModifier(fieldC);   //删除final限制            fieldC.setInt(obj, 33);      //无法篡改            System.out.println("---------------以下是结果----------------");            System.out.println("final属性a篡改后:" + obj.getValueA());            System.out.println("非final属性b篡改后:" + obj.getValueB());            System.out.println("final属性c篡改后:" + obj.getValueC());        } catch (Exception ex) {            ex.printStackTrace();        }    }

输出日志:

final属性a篡改前:1
非final属性b篡改前:2
final属性c篡改前:3
---------------以下是结果----------------
final属性a篡改后:11
非final属性b篡改后:22
final属性c篡改后:3