我们使用字符串时,会用到两种方式:
String s = "字符串";
String s = new String("字符串");
"字符串" 和 new String()的区别:
贴上一段代码
String s1 = "ABC";
String s2 = "ABC";
String s3 = new String("ABC");
String s4 = new String("ABC");
System.out.println(s1 == s2); //true
System.out.println(s2 == s3); //false
System.out.println(s3 == s4); //false
放上一张个人理解的内存示意图:
可以看到栈内存中引用变量s1 和 s2 都是指向常量池中的 “ABC”。所以它们的地址是同一个,所以相等。
而引用变量s3和s4 指向的是堆内存中的String对象,因为堆中分配的地址唯一,所以s3和s4指向的内存地址不同,则不相等。
使用System.identityHashcode() 来查看他们的内存地址是否相同。identityHashcode() 是根据内存地址生成的哈希值
//s1 s2 "ABC" 输出一样的366712642
System.out.println(System.identityHashCode(s1));
System.out.println(System.identityHashCode(s2));
System.out.println( System.identityHashCode("ABC"));
//s3 和 s4
System.out.println(System.identityHashCode(s3)); //1829164700
System.out.println(System.identityHashCode(s4)); //2018699554
String s = "字符串"; 这样的形式只会在常量池中产生一个String对象,且不可更改。
String s = new String("字符串"); 这样的形式会产生两个对象:一个在堆中,一个在常量池中。
关于字符串拼接后是否相等:
String s1 = "我叫字符串";
String s2 = "我叫";
String s3 = s2 + "字符串";
String s4 = "我叫" + "字符串";
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //true
//使用equals来判断
System.out.println(s1.equals(s3)); //true
首先,创建了一个String对象"我叫字符串" 放入常量池中,并指向s1, 又在常量池中创建一个“我叫” 。
s3 = s2 + "字符串",这一段语句的s2是一个变量,加上一个字符串后会返回一个新的内存地址。
s4 = "我叫" + “字符串“,这一段语句的"我叫" 和 “字符串“ 是常量,在编译期就可以确定下来。拼接后是”我叫字符串“,因为常量池的值是唯一的,所以如果找到该字符串就返回其地址,如果没有就在常量池中创建。所以s4和s1的地址指向同一个,返回true。
关于==和equals的区别:
==操作符比较的是两个变量的值是否相等,因为引用类型变量中存的是内存地址,所以使用==比较的是两个引用变量是否指向同一个内存地址,但不能比较指向的内存地址中存的内容。如果是值类型的话,可以直接使用==比较,因为值类型是直接存值的。
equals()该方法来源于Object类,它的原始作用就是比较两个对象内容是否相同。而String类重写后,可以比较两个字符串的值是否相等。
总结下来就是:
==操作符是直接比较变量的值。如果是引用类型变量,则是比较引用地址。
equals()方法是比较内存地址中的值,即判断内容是否相同。
String类方法:
intlength() 返回此字符串的长度。
indexOf() 从索引0处开始,根据给定的字符或者是索引值,得到索引值或是指定字符。
lastIndexOf() 从索引length - 1处开始,根据给定的字符或者是索引值,得到索引值或是指定字符。
booleancontains(CharSequence s) 是否包含指定字符串或者是一段字符序列,如果包含则返回 true。
char charAt(int index) 返回指定索引处的字符。
int codePointAt(int index) 返回指定索引处的字符
int codePointBefore(int index) 返回指定索引之前的字符
int compareTo(String anotherString) 按字典顺序比较两个字符串。
int compareToIgnoreCase(String str) 按字典顺序比较两个字符串,忽略大小写。
String concat(String str) 把传入的字符串连接到该字符串的尾部。
boolean contentEquals(CharSequence cs)可以与 一段字符序列进行比较。
boolean contentEquals(StringBuffer sb)可以与 StringBuffer 进行比较。
static String copyValueOf(char[] data) 将字符数组转成字符串
static String copyValueOf(char[] data, int offset, int count) 指定字符数组的起始和转换数量。
boolean endsWith(String suffix) 测试字符串是否以指定后缀结束。
boolean equals(Object anObject) 将此字符串与指定的对象比较。
boolean equalsIgnoreCase(String anotherString) 两个String进行比较时,忽略大小写。
byte[] getBytes(Charset charset) 将字符串按照指定编码转成字节数组
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 把字符串中指定的内容复制到目标字符数组中。
String intern() 返回字符串对象的规范化表示形式。
boolean isEmpty() 当且仅当 length() 为 0 时返回 true。
boolean matches(String regex) 此字符串是否和该正则表达式匹配。
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) 测试两个字符串的一段区域是否相等。
String replace(char oldChar, char newChar) 用新字符替换旧字符
String replace(CharSequence target, CharSequence replacement) 用一段字符序列替换另一段字符序列
String replaceAll(String regex, String replacement) 满足该字符串正则表达式,就全部替换。
String replaceFirst(String regex, String replacement) 满足该字符串正则表达式,就只替换第一个。
String[] split(String regex) 使用给定的正则来分割字符串。
boolean startsWith(String prefix) 判断是否以指定字符串作为前缀
boolean startsWith(String prefix, int toffset) 从指定的索引处开始,判断是否以指定字符串作为前缀
String substring(int beginIndex, int endIndex) 根据索引值,返回一个新的字符串。
char[] toCharArray() 将此字符串转换为一个新的字符数组。
String toLowerCase() 变小写。
StringtoUpperCase() 变大写。
String toString() 返回此对象本身,即返回一个字符串。
String trim() 返回字符串的副本,忽略前导空白和尾部空白。
static String valueOf() 将给定类型的值或者数组转成字符串。