发布时间:2023-12-01 09:30
目录
1.初识字符串
2.字符串常量池
3.反射修改常量字符串
Java中,字符串类型就是我们用双引号引起来的连续字符,如:\"abcdef\",而\'a\'这种的只是字符,String只是字符串的类型。
那我们接下来看看一些字符串是否相等的例子:
public static void func(String s,char[] array){
s = \"hang\";
array[0] = \'p\';
}
public static void main(String[] args) {
String str = \"abcdef\";
char[] chars = {\'b\',\'i\',\'t\'};
func(str,chars);
System.out.println(str);
System.out.println(Arrays.toString(chars));
}
下面我们看看此题的内存布局:
运行时常量池:当程序把编译好的字节码文件加载到JVM中,会生成一个运行时常量池(存储在方法区)实际上是class文件常量池。
字符串常量池:主要存放字符串常量,本质上是一个哈希表,StringTable.在JDK1.8开始,放在了堆里面。
例2:
String str1 = \"hello\";//双引号引起来的存放到字符串常量池里面
String str2 = new String(\"hello\");
System.out.println(str1 == str2);
//其结果是false
下面是其内存布局:
例2:
String str1 = \"hello\";
String str2 = \"hello\";
System.out.println(str1 == str2);
这其中str1先入常量池,随后str2直接引用常量池中的hello,因此两者相等。并且str2并不会入池。
例3:
String str1 = \"11\";
String str2 = new String(\"1\")+new String(\"1\");
System.out.println(str1 == str2);
例4:
String str2 = new String(\"1\")+new String(\"1\");
str2.intern();//手动入池,字符串常量池没有的时候,就会入池,有则不会入池
String str1 = \"11\";
System.out.println(str1 == str2);
此时两个1互相拼接之后,内存布局和上述相同,可是调用intern( )方法之后,我们将str2手动入池,之后再有str1=11调用常量池中的11,因此结果为true.
但如果我们将str1和str2位置交换,则结果会变为false。这是因为str1先入池,之后intern( )时,常量池已经有11,因此str2不会入池。
String str1 = \"11\";
String str2 = new String(\"1\")+new String(\"1\");
str2.intern();//手动入池,字符串常量池没有的时候,就会入池,有则不会入池
System.out.println(str1 == str2);
如果我们想比较字符串的内容时,则使用equals方法,但在使用之前我们应该先判断str1是否为空
public class TestDemo2 {
public static void main7(String[] args) {
String str1 = null;//代表str1这个引用不指向任何对象
String str3 = \"\";//代表str3这个引用指向的字符串是空的
String str2 = \"11\";//String底层是个value数组,此时11不能被改变,如果想改变,只能用反射
//调用方法之前一定是个引用或者类名,因此一定要防止其为空
System.out.println(str1.equals(str2));
}
public static void main(String[] args) throws NoSuchFieldException {
String str = \"aello\";
Class> c1 = String.class;
// 获取 String 类中的 value 字段. 这个 value 和 String 源码中的 value 是匹配的.
Field valueField = c1.getDeclaredField(\"value\");
// 将这个字段的访问属性设为 true
valueField.setAccessible(true);
// 把 str 中的 value 属性获取到.
char[] value = (char[]) valueField.get(str);
// 修改 value 的值
value[0] = \'h\';
System.out.println(str);
}
//此时通过反射将字符串改为hello