1. 在观察StringBuffer类的toString方法时,发现了个没见过的方法
publicsynchronizedStringtoString() { if (toStringCache==null) { toStringCache=Arrays.copyOfRange(value, 0, count); } returnnewString(toStringCache, true); }
2. 发现它传了一个true进去,然后点进去后
发现它对传进去的true没有做任何操作,学到了一种新的“方法重载思想”,传一个boolean只是为了区分方法
String(char[] value, booleanshare) { // assert share : "unshared not supported";this.value=value; }
在此处我发现这个this.value = value;
此时就很懵,这个是String类里面的value,这个不是不可以修改的么,然后各种查,各种测试
privatefinalcharvalue[];
最后发现这个是一个new String 操作,所以对一个final修饰的value[]来说,此时他还没有被赋值,所以是可以进行第一次赋值的
3. 那么话又说回来了,这个方法和不传boolean的有什么区别呢?
publicString(charvalue[]) { this.value=Arrays.copyOf(value, value.length); } String(char[] value, booleanshare) { // assert share : "unshared not supported";this.value=value; }
我们可以观察到方法的修饰符不同,一个是public的,一个是默认的,也就是只有同包才能访问,StringBuffer与String都是属于java.lang包下的,所以StringBuffer可以使用,而我们是使用不了的,因为如果交给我们使用的话,可能会违反String是不可修改的原则的。
- 例如如下代码:不能运行,只是示范
此时传入的b是引用,s的value中保存的也是b的引用,所以可以认为此时的b与String中的value是同一个对象,此时修改b[1]的值的时候,String中final修饰的value就被修改了,很明显不符合String的定义。
char [] b= {'b','c','1'}; Strings=newString(b, true); b[1] ='a';
而直接传入char[]数组的,是调用数组拷贝,将传入的值一一赋值到String内置的value数组中,他们两个是不同的两个对象,也就保证了String类的不可修改
4. 最后我们来强行调用一下,利用反射
privatestaticvoidtest07() throwsNoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { char[] a= {'1','f','l'}; Class<String>clazz=String.class; Constructor<String>constructor=clazz.getDeclaredConstructor(char[].class, boolean.class); constructor.setAccessible(true); Strings=constructor.newInstance(a, true); System.out.println(s); //此时修改a[1]的值a[1]='c'; System.out.println(s); }
我们观察打印输出,可以发现,String对象被我们修改了,也验证了我们前面的说法
1fl
1cl