Java反射获取private属性和方法(子类,父类,祖先….)
先来看一个例子:String可变还是不可变?
大家都应该知道,或者听过,String类是不可变的,为什么呢?因为String其实使用一个
private final char [] value;
来保存字符的;final,private,明显就不让你改了啊。但是,大家请看:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
输出(猜猜看,和你想的一不一样呢?):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
如果,你都答对了,恭喜你,那请直接跳到 反射用法.
否则:请看下面分析
先摘一段官方intern()的注释:
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
3个点:
* 1.常量池(JVM中就是方法区)是由 String 这个class来私有的管理的。*
* 2.调用intern()时,会查看常量池是否存在这个String对象,这是通过equals()方法来判断的。*
* 3.如果存在,则返回常量池中那个String对象,否则,加入到常量池,并返回当前对象。*
ps : equals()方法,首先是看obj1==obj2,也就是引用地址是否相等,如果等则返回true,然后是逐个字符比较。
ok,有了以上知识。其实到这里你自己也可以分析出来了。
我们来分析一下
首先,String a="abc";
这句话在内存(常量池)中放入了一个String对象:“abc”(内存地址假设为0x123,由char [] value = [‘a’,’b’,’c’]保存),
然后第2~5行,我们先不管语法,只要知道是把“abc”这个字符串的第三个字符’c’替换为’@’,
此时char [] value = [‘a’,’b’,’c’] 变为了char [] value = [‘a’,’b’,’@’],String这个class对象管理的还是“abc”这个对象。
接下来 String b="abc"
,这句话会从常量池中寻找“abc”,此时会发现常量池中“abc”是存在的,于是,b就指向了“abc”,b其实就是“abc”的位置的一个引用,a也是一个“abc”位置的引用。
那么接下来就是顺理成章了:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
如果仔细想想,其实还是有疑问,在这里就不展开了,不然偏题了,因为我对底层也不懂,intern是c++实现的,具体看这篇:
反射
反射,RTTI,Class对象,这些就不说了,看一段代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
这段代码输入是一个Class的对象,递归输出这个类的父类,祖父类直到Object类的所有方法和域。
再看一段:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
ok,这段代码输入任意一个对象,调用上面那段代码的方法getClassFieldAndMethod(),这样你就知道这个对象都有些什么域,什么方法了,再通过域的名称,就可以获取当前这个对象的域的值,进而可以修改了!!
是不是很简单,从此以后谁都不能限制你在Java程序里面为所欲为了!