Day017 String类
Posted 南方风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day017 String类相关的知识,希望对你有一定的参考价值。
String
String类特点
- String类:代表字符串。Java程序中所有的字符串字面值(如“abc”)都作为此类的实例实现。
- String是一个final类,代表不可变的字符序列。
- 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
- String对象的字符内容是存储在一个字符数组value[]中的。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
注意点:
-
String声明为final,不可以被继承。
-
String实现了Serializable接口:表示字符串是支持序列化的。
实现了Comparable接口:表示String可以比较大小
-
String内部定义了final char[] value用于存储字符串数据
-
String:代表不可变的字符序列。简称:不可变性。
体现:
-
当对字符串重新复制时,需要重写指定内存区域赋值,不能使用原有的value[]赋值。
-
当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能在原有的value[]上拼接。
-
当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值。
-
-
通过字面量的方式(区别于new),给一个字符串赋值,此时的字符串声明在字符串常量池中。
-
字符串常量池中是不会存储相同内容的字符串的。
String s1="abc";//字面量的定义方式 String s2="abc"; System.out.println(s1==s2);//比较s1和s2的地址值 s1="hello"; System.out.println(s1); System.out.println(s2); System.out.println("*********************"); String s3="abc"; s3+="def"; System.out.println(s3);//abcdef System.out.println(s2); System.out.println("*********************"); String s4="abc"; String s5=s4.replace(\'a\',\'m\');//把a改成m System.out.println(s4);//abc System.out.println(s5);//mbc
输出结果
true hello abc ********************* abcdef abc ********************* abc mbc
分析:
-
s1==s2,说明s1和s2指向的是同一块内存,而将s1赋为hello之后,没有影响到s2,说明不是改了s1的内存里的值,而是重新开辟了一块内存空间,里面存的是hello,s1指向hello的地址。
-
同理,s2和s3刚开始都是指向同一片内存,而拼接后s2没有改变,说明拼接也是新开辟了一块内存空间。
-
s4改了之后,s4还是abc,说明也是重新开辟了一块内存空间,再s5指向该内存空间。
-
String对象的创建
方式一:字面量的方式赋值
String str = "hello";
方式二:本质上 this.value=new char[0];
String s1 = new String();
方式三:本质上 this.value=original.value;
String s2 = new String(String original);
方式四:本质上 this.value=Array.copyOf(value,value.length)
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
//字面量方式定义,值放在常量池中
String s1="javaEE";
String s2="javaEE";
//new创建,值放在堆中
String s3=new String("javaEE");
String s4=new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
输出结果
true
false
false
false
String的不同拼接
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
String s8=s5.intern();//返回值得到的s8使用的常量值中已经存在的"javaEEhadoop"的地址
System.out.println(s8==s4);//true
输出结果
true
false
false
false
false
false
false
true
结论:
-
常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量。
-
只要拼接的有变量参与,结果就在堆中。
-
如果拼接的结果调用intern()方法,返回值就在常量池中。
一道面试题
public class StringTest {
String str=new String("good");
char[] ch={\'t\',\'e\',\'s\',\'t\'};
public void change(String str,char ch[]){
str="test ok";
ch[0]=\'b\';
}
public static void main(String[] args) {
StringTest ex=new StringTest();
ex.change(ex.str,ex.ch);
System.out.println(ex.str+" and ");
System.out.println(ex.ch);
}
}
输出结果
good and
best
分析:
- 对于基本数据类型,是值传递,引用类型,是传递引用类型的地址,所以char[]数组被改了。
- 为什么String没改,因为String在赋值时有不可变性,会新开辟一片内存空间。
以上是关于Day017 String类的主要内容,如果未能解决你的问题,请参考以下文章