我们知道java的字符串类型String被设计成不可变的。那么我们还有办法改变它的值吗?
先来看一下,截取自jdk1.8.0_151的java.lang.String类的声明:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
String被设计成final类,即不可继承,同时实现了序列化等接口。
再来看一下,String的成员变量:
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
总共有三个成员变量,出来hash被设置为非final常量,其余全是常量。更重要的是value被设计为final,以维护String的不可变性。
我们利用反射来打破这种不可变性,看如下代码:
package com.modest.cainiao;
import java.lang.reflect.Field;
/**
*
* @author heng.guo
* @date 2018-07-28
*
*/
public class StringImmutable {
public static void main(String[] args) {
String str = "ABCD";
System.out.println("str = " + str);
System.out.println("hashCode = " + str.hashCode());
try {
Field valueField = String.class.getDeclaredField("value");
//value域是final private的,这里设置可访问
valueField.setAccessible(true);
char[] valueCharArr = (char[]) valueField.get(str);
valueCharArr[0] = 'G';
//此处输出第一组结果
System.out.println("str = " + str);
System.out.println("hashCode = " + str.hashCode());
valueField.set(str, new char[] {'1', '2'});
//此处输出第二组结果
System.out.println("str = " + str);
System.out.println("hashCode = " + str.hashCode());
} catch (NoSuchFieldException | SecurityException
| IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
执行上述代码,我们观察到结果是这样的:
看起来,我们成功的修改了,str的值。
那如果我们把str的声明修改成这样呢?
final String str = "ABCD";
运行一下,看一下结果:
str没有改变。
那如果我们输出str的时候,调用它的toString()方法呢?即,输出时,改为以下方式:
System.out.println("str = " + str.toString());
运行结果如下:
str的值看起来被修改了。那么我们看看String类中toString方法(截取自JDK1.8.0_151版本)的声明:
/**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString() {
return this;
}
【备注】:在JDK1.9中,String的value被设计成byte[],不再是char[]了。
【问题】:加上final以后为什么值没有变,换成toString()之后为什么变了?
版权声明:本文为guohengcook原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。