String类
概述
- String是不可变类,即一旦一个String对象被创建, 包含在这个对象中的字符序列是不可改变的, 直至该对象被销毁。
- String类是final类,不能有子类。
创建字符串对象
-
使用new关键字
String s1 = new String("ab");
-
使用字符串常量直接赋值
String s2 = "abc";
-
使用”+”运算符进行字符串连接
String s3 = "abc" + "d"; String s4 = s3 + 5; //abcd5
常量池概念和创建对象规则
常量池概念:
Java运行时会维护一个String Pool(String池), 也叫“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。运行时常量池(Runtime Constant Pool)是方法区(Method Area)的一部分,是各线程共享的内存区域。
String对象的创建很讲究,关键是要明白其原理。
-
当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个s在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
-
使用直接指定或者使用纯字符串(常量)串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则不创建!但绝不会在堆区再去创建该String对象。
public static void main(String[] args){ String a = "a1"; String b = "a"+ 1; System.out.println(a==b); }//true
-
使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆区创建一个String对象。最后指向堆内存中的对象
public static void main(String[] args){ String a = "ab"; String k = "b"; String b = "a"+ k;//编译器不能确定为常量(会在堆区创建一个String对象) System.out.println(a==b); }//false
-
public static void main(String[] args){ String a = "ab"; final String k = "b"; String b = "a"+ k; //k加final后是常量,可以在编译器确定b System.out.println(a==b); }//true
-
public static void main(String[] args){ String a = "ab"; final String k = getK(); String b = "a"+ k;//k是通过函数返回的,虽然我们知道它是final的,但程序不能确定具体返回啥,所以要到运行期才知道k的值。理论上,整个方法的返回值也变成了一个变量。 System.out.println(a==b); }//false private static String getK(){ return "b"; }
-
private static String a = "ab"; public static void main(String[] args){ String s1 = "a"; String s2 = "b"; String s = s1 + s2;//+的用法 System.out.println(s == a); System.out.println(s.intern() == a);//intern的含义(将字符串堆对象放入常量池,并返回指向放入常量池后的引用) }//flase true
-
Java中,只要使用new关键字来创建对象,则一定会(在堆区)创建一个新的对象。并且让引用指向堆中的对象。
private static String a = new String("ab");//只要使用new关键字来创建对象,则一定会(在堆区)创建一个新的对象。 public static void main(String[] args){ String s1 = "a"; String s2 = "b"; String s = s1 + s2; System.out.println(s == a); System.out.println(s.intern() == a); System.out.println(s.intern() == a.intern()); }//flase false true
-
问:
new String("i am");
这句代码会创建几个对象?
字符串常用方法
计算字符串长度的方法
public int length(); //返回字符串字符的个数。
获得新字符串对象的常用方法
-
public String concat(String str) 在原有字符串的尾部添加参数字符串,返回一个新的字符串(总是堆内存中的对象),如果str的长度为0,则返回原字符串。str不能为空null。
-
public String subString(int beginIndex) 获得从beginIndex开始到结束的子字符串。( 包括beginIndex位置的字符)
-
public String subString(int beginIndex,int endIndex) 获得从beginIndex开始到endIndex的子字符串。( 包括beginIndex位置的字符,但不包含endIndex)
-
public String toLowerCase() 把字符串中的英文字符全部转换为小写字符,返回值为转换后的新的字符串。
-
public String toUpperCase() 把字符串中的英文字符全部转换为大写字符,返回值为转换后的新的字符串。
-
public String trim() 把字符串中的首尾的空白字符去掉,返回去掉首尾空白字符的新字符串
-
public String replace(CharSequence target, CharSequence replacement) 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串
String src = new String("ab43a2c43d"); System.out.println(src.replace("3","f")); =>ab4f2c4fd
-
public String replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String src = new String("ab43a2c43d"); System.out.println(src.replace('3','f')); =>ab4f2c4fd
字符串比较
-
”==”表示判断该两个字符串是否为同一对象,即在内存中的地址是否一样。如果一样则返回true 否则返回false; 和我们通常的是否为同一对象的是一样的。
-
boolean equals(Object anObject) 将此字符串与指定的对象比较。注意此时比较的是内容是否相等(字符串类对此方法进行了覆写)。
例如:
String s1 = new String(“abc”); String s2 = “abc”
则:
s1==s2 //false s1.equals(s2); //true
-
boolean equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。
例如:
”abc”. equalsIgnoreCase(“AbC”); // true
-
int compareTo(String value) 返回参与比较的前后两个字符串的asc码的差值
-
String a="a",b="b"; System.out.println(a.compareto.b); 则输出-1; 若a="a",b="a"则输出0; 若a="b",b="a"则输出1;
-
单个字符这样比较,若字符串比较长呢?
若a="ab",b="b",则输出-1; 若a="abcdef",b="b"则输出-1;
也就是说,如果两个字符串首字母不同,则该方法返回首字母的asc码的差值;
-
如果首字母相同呢?
若a="ab",b="a",输出1; 若a="abcdef",b="a"输出5; 若a="abcdef",b="abc"输出3; 若a="abcdef",b="ace"输出-1;
即:参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值,如果两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值。
提示:查看单个字符的asc码的值(使用int 接收 char字符,再打印输出即可)
int i ='a'; int j = 'b'; System.out.println(i); System.out.println(j);
-
-
int compareToIgnoreCase(String val) 按ACS码顺序比较两个字符串,不考虑大小写
-
boolean startsWith(String value) 检查一个字符串是否以参数字符串开始。
-
boolean endsWith(String value) 检查一个字符串是否以参数个字符串结束。
字符串查找
- public int indexOf(String str); 返回 str 在字符串中的第一次出现的下标的位置,如果不存在,返回-1
- public int lastIndexOf(String str);返回 str 在字符串中的最后一次出现的下标的位置,如果不存在,返回-1
- public char charAt(int index) ;返回字符串的 index 下标位置的字符。
- public boolean contains(CharSequence s); 判断字符串中是否包含 s 。
其他类型转换成字符串
在String类中定义了一些静态的重载方法
public static String valueOf(…);
可以将基本类型数据、Object类型转换为字符串。如:
public static String valueOf(double d);//把double类型数据转成字符串
public static String valueOf(Object obj);//调用obj的toString()方法得到它的字符串表示形式。
还有一种最简单的方法:
-
把任意对象、基本数据类型与一个空字符串相连接则可以直接转换成字符串,与上面效果相同。
如:
int i = 18; String str = i + "";
String 与 char[] 的 转换
- char[] toCharArray();拷贝一份String中的所有字符。返回char[]
- new String(c);根据默认编码,将char[]转成String
- new String(value, offset, count);根据默认编码,将value(char[]),从offset(包含offset)位置开始,截取count个字符,转成String。
String 与 byte[] 的 转换
- byte[] getBytes();根据系统默认的编码,得到字符串的byte[]。
- byte[] getBytes("UTF-8");根据UTF-8编码, 得到的字符串的byte[]。
- new String(bytes);根据默认编码,将byte[]转成String。
- new String(bytes,"UTF-8");根据UTF-8编码,将byte[]转成String。
- new String(bytes, offset, length);根据默认编码,将bytes(byte[]),从offset(包含offset)位置开始,取count个字节转成String。
- new String(bytes, offset, length,"UTF-8");根据UTF-8编码,将bytes(byte[]),从offset(包含offset)位置开始,取count个字节转成String。