字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。 String
类是不可改变的,所以一旦创建了 String 对象,那它的值就无法改变了。 如果需要对字符串做很多修改,那么应该选择使用
StringBuffer & StringBuilder 类
为什么String类是不可改变的?
String s = "AAAA"; System.out.println("s = " + s); s = "BBBB"; System.out.println("s = " + s);
输出结果:
AAAA BBBB
从结果上看是改变了,但为什么说String对象是不可变的呢?
原因在于实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = “BBBB”; 创建了一个新的对象 “BBBB”,而原来的 “AAAA” 还存在于内存中。
如图:
或者根据 jdk 的源码来分析。
字符串实际上就是一个 char 数组,并且内部就是封装了一个 char 数组。
并且这里 char 数组是被 final 修饰的:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
并且 String 中的所有的方法,都是对于 char 数组的改变,只要是对它的改变,方法内部都是返回一个新的 String 实例。
Java:String、StringBuffer 和 StringBuilder 的区别
String:字符串常量,字符串长度不可变。Java中String 是immutable(不可变)的。用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改。
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 StringBuffer,如果想转成 String 类型,可以调用 StringBuffer 的 toString() 方法。Java.lang.StringBuffer 线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。
StringBuilder:字符串变量(非线程安全)。在内部 StringBuilder 对象被当作是一个包含字符序列的变长数组。
基本原则:
如果要操作少量的数据用 String ;
单线程操作大量数据用StringBuilder ;
多线程操作大量数据,用StringBuffer。
String类支持的方法:
获取字符串长度 用于获取有关对象的信息的方法称为访问器方法。
String 类的一个访问器方法是 length() 方法
1、length() 方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法;
2、length 属性是针对 Java 中的数组来说的,要求数组的长度可以用其 length 属性;
3、Java 中的 size() 方法是针对泛型集合说的, 如果想看这个泛型有多少个元素, 就调用此方法来查看!
连接字符串
concat() 方法
'+'操作符
String a = "a"; String b = "b"; String c = a + b
相当于:
String c = new StringBuffer().append(a).append(b).toString();
对于字符串的加运算,当编译成 class 文件时,会自动编译为 StringBuffer 来进行字符串的连接操作。
同时对于字符串常量池:
当一个字符串是一个字面量时,它会被放到一个常量池中,等待复用。
String a = "saff"; String b = "saff"; String c = new String("saff"); System.out.println(a.equal(b)); // true System.out.println(a.equal(c)); // true
这个就是字符串的常量池。
创建格式化字符串
String 类的静态方法 format() 能用来创建可复用的格式化字符串,而不仅仅是用于一次打印输出。
返回指定索引处的 char 值
charAt() 方法用于返回指定索引处的字符。索引范围为从 0 到 length() - 1。
字符串与对象进行比较、按字典顺序比较两个字符串
int compareTo(Object o)
compareTo(String anotherString)
关于这个方法,不管参数是对象还是字符串,最终要比较的都是两个字符串的不同,以下称调用方法那边的为原字符串,方法参数里的为参数字符串。
这个方法分为两种比较方式:
1、不同的字符在较短字符串长度之内时
2、不同的字符在较短字符串长度之外时
看下 compareTo 的源码:
/* *如果参数字符串等于此字符串,则返回值 0; *如果此字符串按字典顺序小于字符串参数,则*返回一个小于 0 的值; *如果此字符串按字典顺序大于字符串参数,则返回一个大于 0 的值。 */ public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; //取数组长度里面最小的 int lim = Math.min(len1, len2); // 获得两个数组,这两个数组就是string的属性 char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { //获取第K的字符,进行比较 char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { //Java使用的是Unicode编码,因此返回这两个字符的Unicode差值。 return c1 - c2; } k++; } //如果前lim个字符都相同,那么就返回长度差。 return len1 - len2; }
- 1、取得string的value数组
- 2、取得value数组里面的元素
- 3、按照unicode值进行比较
- 4、返回比较的值
String a = "a"; String b = "b"; System.out.println(a.compareTo(b));
输出值 -1。
String a = "b"; String b = "a"; System.out.println(a.compareTo(b));
输出值 1。
String a = "a"; String b = "a"; System.out.println(a.compareTo(b));
输出 0。
两个字符串首字母不同,则该方法返回首字母的 asc 码的差值。
String a = "abc"; String b = "bcdfg"; System.out.println(a.compareTo(b));
输出 -1。
参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的 ascii 码差值。
String a = "abc"; String b = "abedfg"; System.out.println(a.compareTo(b));
输出 -2。
两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值。
String a = "abc"; String b = "abcdefg"; System.out.println(a.compareTo(b));
输出 -4。
string a = "abcde"; String b = "abcd"; System.out.println(a.compareTo(b));
输出 1。
目前 compareTo 项目中的用途是比较版本号的高低。
String a = "1.0.0"; String b = "1.0.1"; System.out.println(a.compareTo(b));
输出 -1。