修改Java中的数字

逛某乎时,看到一个关于Java的有意思的回答你可以通过反射把false变成true!.

于是,一时兴起,顺手试试反射修改Integer吧.

然后就有了下面这段代码.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.lang.reflect.Array;

public class ChangeInt {
public static void main(String[] args) throws Exception {
var cls = Integer.class.getDeclaredClasses()[0];
var cache = cls.getDeclaredField("cache");
cache.setAccessible(true);
var arr = cache.get(null);
for(int i = 0; i < 256; ++i){
Array.set(arr, i, 0);
}
Integer i = 111;
int pi = 111;
Integer ii = Integer.valueOf(111);
System.out.printf("i: %d, pi: %d, ii: %d\n", i, pi, ii);
}
}

于是,这段代码的输出是:

1
i: 0, pi: 0, ii: 0

同样,修改Byte, ShortLong中的cache,就可以改变对应类型的数字.
不过,这样还是只能修改一个byte范围内的数字.

但是,我们可以通过修改Integer::DigitOnes, Integer::DigitTensInteger::digits的值,来改变所有整形数字的输出:

1
2
3
4
5
6
7
var field = Integer.class.getDeclaredField("digits");
field.setAccessible(true);
var digits = field.get(null);
for(int i = 0; i < Array.getLength(digits); ++i){
Array.set(digits, i, (char)('1' + Math.random() * 10));
}
System.out.println(Integer.toString(0x123456, 16));

上述代码一个可能的输出是:

1
672929