大家知道String是final型的,是不可变得,但是通过反射却是可以改变String的值。
先了解下String类
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash;
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
}
String 类是final型的,并且继承了序列化,比较字符串等接口。
public static void main(String[] args){
String s1 = "abc";
String s2 = "abc";
String s3="dbc";
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
char[] c = (char[]) f.get(s1);
c[0]='d';
System.out.println(s1);
System.out.println(s1==s2);
System.out.println("s1.equals(s2) "+s1.equals(s2));
System.out.println("s2.equals(s3) "+s2.equals(s3));
System.out.println("s1.equals(s3) "+s1.equals(s3));
System.out.println(s1+" "+s2+" "+s3);
System.out.println(s1.hashCode()+" "+s2.hashCode()+ " "+s3.hashCode());
}
结果
dbc
true
s1.equals(s2) true//因为地址没变所以true
s2.equals(s3) true//s1和s2是同一块地址,改变s1为dbc,s2指向的也是dbc.
s1.equals(s3) true
dbc dbc dbc
99237 99237 99237
问题
Java反射机制调用私有方法,是不是破坏了Java的封装性?
没有破坏,Java语言本身是静态的,为了能让语言具有动态编程的特性,必须要有反射机制。而反射机制本身就是底层的处理,不可能按表层的封转特性来处理。也就是说不给调用私有方法的能力,很多程序受到局限。