一、String的基本认识
1、String的两种实例化方式
第一种方式较为常用,是直接赋值的方法,如下面的代码,但String本身是一个类,类存在构造方法,所以String还可以通过构造方法实例化。
//第一种方式,直接赋值
String str1 = "Hello";
//第二种方式,通过构造方法
String str2 = new String("Hello!");
实例化好的对象str1,str2存放在栈中,是引用(相当于C语言中的地址)。而“Hello”,“Hello!”则存放在堆中
两种实例化对象的区别:
1、直接赋值
String str1 = "Java is best";
String str2 = "Java is best";
String str3 = "Java is best";
String类的设计使用了共享的设计模式 只适用于直接赋值法!!!
在JVM底层实际上会自动维护一个对象池(字符串对象池),如果采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)会直接保存到这个对象池中。如果下次继续使用直接赋值的方式声明String对象,则会优先查看对象池,如果有指定内容,将直接进行引用;如果没有,则开辟新的字符串对象,并将其保存在对象池值中,并供下次使用。如下图所示。
这样可以节省大量的空间!对象池其实就是一个对象数组。
用直接赋值法创建第一个对象str1时,对象池中什么也没有,所以在对象池中添加“Java is best”,用直接赋值法创建第二个对象str2时,查看对象池,对象池中有“Java is best”,将直接进行引用(如果没有,则开辟新的字符串对象,并将其保存在对象池值中,并供下次使用);用直接赋值法创建第三个对象str3时,查看对象池,对象池中有“Java is best”,将直接进行引用。
2、采用构造方法实例化
String str4 = new String("Java is best");
刚开始时"Java is best"是一个匿名对象,如下图所示
new String()时会在堆上开辟空间存放"Java is best",并且将str4指向它,刚刚的匿名对象就会被抛弃了,成为垃圾对象(栈上没有地址指向的对象),等待垃圾回收器的回收。如下图
所以通过构造方法实例化,会造成大量的垃圾空间,它会开辟两个空间,其中一个是匿名对象,实例完成后成为垃圾空间,另一个是真正的对象。
既然通过构造方法是浪费空间的,那有没有方法改变这个? 有的! 那就是String对象入池操作
//将str入池--->共享
String str = new String("Hello").intern();
查看Sting的API
会发现
1、String在java.lang包底下(这个包是自动导入的)
2、通过
public final class String extends Object implements Serializable, Comparable<String>, CharSequence
知道String是Object的子类且不可被继承
2、String的构造方法
可以通过以下任意一个构造方法来创建String对象,标明为已弃用的最好就不要用了,因为它在版本升级过程中,未来版本有可能就不支持了
3、字符串比较
public class Strings1{
public static void main(String[] args){
int x = 10;
int y = 10;
System.out.println(x==y);//true
String str1 = "Java is best";
String str2 = "Java is best";
String str3 = new String("Java is best");
System.out.println(str1==str2);//true
System.out.println(str1==str3);//false
}
}
上述代码中的变量,在内存中的情况如下图所示:(具体是为什么,在字符串入池时讲过啦,见两种实例化对象的区别)
、
至于为什么为会出现这样的结果,是因为代码中的“==”比较的值是栈空间的值。
对于基本数据类型来说,他们的值本身就存放在栈空间,
而对于引用数据类型来说,他们真正的值存放在堆空间,对象的引用(可以看成地址)存放在栈空间。所以“==”比较的是他们的地址的值,也就是看他们是否是同一个对象,而非String的内容
如果要比较String的内容,可以用equals()这个方法!在String中equals方法比较的是字符串内容。
其实在Java中所有的类都继承自Object类,而equals就是Object中的方法,这个方法本质上就是“==”,比较对象是否是一个对象。哪为什么在String中equals不这么用呢?是因为String类覆写了Object的方法。
public class Strings1{
public static void main(String[] args){
String str1 = "Hello";
String str3 = new String("Hello");
System.out.println(str1.equals(str3));//true
}
}
//这是Object的equals() 的源代码 本质上是==
public boolean equals(Object obj) {
return (this == obj);
}
//这是String的equals()的源代码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
小技巧:在字符串的值与匿名的字符串equals()比较时,可以将匿名字符串放在前面,因为匿名字符串不可能为空,即不可能出现“NullPointerException”问题
String str4 = null;
System.out.println("Hello".equals(str4));//false
System.out.println(str4.equals("Hello"));//NullPointerException
4、字符串不可变
字符串一旦定义就不能改变!------>一旦改变就会产生新的字符串对象
因为Java语言对于字符串的底层实现是字符数组,数组的缺陷是长度固定,所以在字符串定义常量时,他的内容不可改变。
就像下面的代码一样,一共创建出了5个对象,显然这样写代码是不好的。如果对字符串有大量的改变,java中提供了两个类:StringBuffer和StringBuilder可以解决这个问题。
public static void main(String[] args){
String str1 = "Hello";
str1 = str1+" world";
str1 += "!!!";
System.out.println(str1);//"Hello world!!!"
}
执行完String str1 = "Hello";后,内存分派如下图:
执行完str1 = str1+" world";后,内存分派如下图:
注意:垃圾对象不在对象池中,如果给匿名对象赋值了,才会将匿名对象放在池子中。因为如果将每一个匿名对象都放在池子中,池子将会很快被填满,而且匿名对象因为没有引用,所以只能用一次,放在池子中时没有意义的,只是占用了空间。
执行完str1 += "!!!";后,内存分派如下图:
当然了,如果你写了这样一个代码:String str = "Hello"+" World"+"!!!";
Java在编译成字节码时会优化为这样String str = "Hello World!!!";并且将它放在池子中。
二、关于String的方法
查看String的API
-
-
Modifier and Type Method and Description char
charAt(int index)
返回
char
指定索引处的值。int
codePointAt(int index)
返回指定索引处的字符(Unicode代码点)。
int
codePointBefore(int index)
返回指定索引之前的字符(Unicode代码点)。
int
codePointCount(int beginIndex, int endIndex)
返回此
String
指定文本范围内的Unicode代码点数。int
compareTo(String anotherString)
按字典顺序比较两个字符串。
int
compareToIgnoreCase(String str)
按字典顺序比较两个字符串,忽略病例差异。
String
concat(String str)
将指定的字符串连接到该字符串的末尾。
boolean
contains(CharSequence s)
当且仅当此字符串包含指定的char值序列时才返回true。
boolean
contentEquals(CharSequence cs)
将此字符串与指定的CharSequence进行
CharSequence
。boolean
contentEquals(StringBuffer sb)
将此字符串与指定的StringBuffer进行
StringBuffer
。static String
copyValueOf(char[] data)
相当于
valueOf(char[])
。static String
copyValueOf(char[] data, int offset, int count)
boolean
endsWith(String suffix)
测试此字符串是否以指定的后缀结尾。
boolean
equals(Object anObject)
将此字符串与指定对象进行比较。
boolean
equalsIgnoreCase(String anotherString)
将此
String
与其他String
比较,忽略案例注意事项。static String
format(Locale l, String format, Object... args)
使用指定的区域设置,格式字符串和参数返回格式化的字符串。
static String
format(String format, Object... args)
使用指定的格式字符串和参数返回格式化的字符串。
byte[]
getBytes()
使用平台的默认字符集将此
String
编码为字节序列,将结果存储到新的字节数组中。byte[]
getBytes(Charset charset)
使用给定的charset将该
String
编码为字节序列,将结果存储到新的字节数组中。void
getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin)
已弃用此方法无法将字符正确转换为字节。 从JDK 1.1开始,首选的方法是通过
getBytes()
方法,该方法使用平台的默认字符集。byte[]
getBytes(String charsetName)
使用命名的字符集将此
String
编码为字节序列,将结果存储到新的字节数组中。void
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
将此字符串中的字符复制到目标字符数组中。
int
hashCode()
返回此字符串的哈希码。
int
indexOf(int ch)
返回指定字符第一次出现的字符串内的索引。
int
indexOf(int ch, int fromIndex)
返回指定字符第一次出现的字符串内的索引,以指定的索引开始搜索。
int
indexOf(String str)
返回指定子字符串第一次出现的字符串内的索引。
int
indexOf(String str, int fromIndex)
返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。
String
intern()
返回字符串对象的规范表示。
boolean
isEmpty()
返回
true
如果,且仅当length()
为0
。static String
join(CharSequence delimiter, CharSequence... elements)
返回一个新的字符串,由
CharSequence elements
的副本组成,并附有指定的delimiter的delimiter
。static String
join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
返回一个新
String
的副本组成CharSequence elements
与指定的副本一起加入delimiter
。int
lastIndexOf(int ch)
返回指定字符的最后一次出现的字符串中的索引。
int
lastIndexOf(int ch, int fromIndex)
返回指定字符的最后一次出现的字符串中的索引,从指定的索引开始向后搜索。
int
lastIndexOf(String str)
返回指定子字符串最后一次出现的字符串中的索引。
int
lastIndexOf(String str, int fromIndex)
返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向后搜索。
int
length()
返回此字符串的长度。
boolean
matches(String regex)
告诉这个字符串是否匹配给定的 regular expression 。
int
offsetByCodePoints(int index, int codePointOffset)
返回此
String
内的指数,与index
codePointOffset
代码点。boolean
regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
boolean
regionMatches(int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
String
replace(char oldChar, char newChar)
返回从替换所有出现的导致一个字符串
oldChar
在此字符串newChar
。String
replace(CharSequence target, CharSequence replacement)
将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列。
String
replaceAll(String regex, String replacement)
用给定的替换替换与给定的 regular expression匹配的此字符串的每个子字符串。
String
replaceFirst(String regex, String replacement)
用给定的替换替换与给定的 regular expression匹配的此字符串的第一个子字符串。
String[]
split(String regex)
将此字符串分割为给定的 regular expression的匹配。
String[]
split(String regex, int limit)
将这个字符串拆分为给定的 regular expression的匹配。
boolean
startsWith(String prefix)
测试此字符串是否以指定的前缀开头。
boolean
startsWith(String prefix, int toffset)
测试在指定索引处开始的此字符串的子字符串是否以指定的前缀开头。
CharSequence
subSequence(int beginIndex, int endIndex)
返回一个字符序列,该序列是该序列的子序列。
String
substring(int beginIndex)
返回一个字符串,该字符串是此字符串的子字符串。
String
substring(int beginIndex, int endIndex)
返回一个字符串,该字符串是此字符串的子字符串。
char[]
toCharArray()
将此字符串转换为新的字符数组。
String
toLowerCase()
将所有在此字符
String
使用默认语言环境的规则,以小写。String
toLowerCase(Locale locale)
将所有在此字符
String
,以降低使用给定的规则情况下Locale
。String
toString()
此对象(已经是字符串!)本身已被返回。
String
toUpperCase()
将所有在此字符
String
使用默认语言环境的规则大写。String
toUpperCase(Locale locale)
将所有在此字符
String
使用给定的规则,大写Locale
。String
trim()
返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。
static String
valueOf(boolean b)
返回
boolean
参数的字符串boolean
形式。static String
valueOf(char c)
返回
char
参数的字符串char
形式。static String
valueOf(char[] data)
返回
char
数组参数的字符串char
形式。static String
valueOf(char[] data, int offset, int count)
返回
char
数组参数的特定子阵列的字符串char
形式。static String
valueOf(double d)
返回
double
参数的字符串double
形式。static String
valueOf(float f)
返回
float
参数的字符串float
形式。static String
valueOf(int i)
返回
int
参数的字符串int
形式。static String
valueOf(long l)
返回
long
参数的字符串long
形式。static String
valueOf(Object obj)
返回
Object
参数的字符串Object
形式。
-