这是学习中用到的一些基础知识
String 是经常会用到的一个类,学习的过程中发现的东西进行的汇总。
1. 初始化方面:
String类是一个比较特别的类,初始化的时候有种简化的特殊语法。
1>String s = "abc";
而按照正规的语法来说,应该是:
2>String s = new String ("abc");
建议使用1>的方式,原因在于这样比较节省内存空间,从其他网站上照抄下来的说法是,【只是按照面向对象的标准语法,在内存使用上存在比较大的浪费。例如 String s = new String(“abc”);实际上创建了两个String对象,一个是”abc”对象,存储在常量空间中,一个是使用new关键字为对象s申请的空间。】
下面是简单的代码
1 String a = "abc";2 String b = "abc";3 System.out.println(a==b);
打印的结果是True。这里的代码含义在于,创建了String类型的引用变量,a和b,a和b指向了值为"abc"的String类,至于是不是新建的String类型的对象,需要根据代码的前后文进行分析(因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象)。结果为True,代表这至少第二行代码没有重新创建一个String类型的对象,而是指向了存在的"abc"的对象,所以a 和 b 指向的是同一个对象,必然两者是相等的。
再如下面的代码:
1 String d = new String("abc");2 String e = new String("abc");3 System.out.println(d==e);
打印的结果是False,即 d, e两个String类型的引用是指向不同的对象,1,2行代码的处理逻辑是: 不管其字符串值是否相等,是否有必要创建新对象,都会创建新的对象。
另外研究到这里的时候,发现代码1中,提出了一个设计模式的思想-享元模式,即复用内存中已经存在的对象,降低系统创建对象实例的性能消耗。至于更多的分析可能会随着学习逐步的深入
2. String的只读特性
String是一个常量,在初始化的时候,一旦创建就不能再被改变,所以看起来是修改了String值的方法,其内部的逻辑并非如此。如下面的代码:
1 String a1 = "first";2 System.out.println(a1 + ", second");
打印之后是“first, second”,其实内部逻辑上来看,其实是生成了一个新的String对象,而不是在原有的String对象上追加内容。
而java的内部处理方式上有说法是通过StringBuilder 这个类来实现字符串的拼接。所以大胆假设下,以上的代码等同于如下的实现方式:
1 StringBuilder stringBuilder = newStringBuilder();2 stringBuilder.append(a1);3 stringBuilder.append(", second");4 System.out.println(stringBuilder.tostring());
通过上面的代码可以看出,如果假设是成立的情况下,在进行字符串拼接的时候如果使用的“String + ”的方式进行的,而在java内部是通过StringBuilder的方式来实现的话,那会创建一个StringBuilder对象来处理,单个的情况下不会有太多额外消耗,但是如果在循环体中使用了“String +”的方式,会不断进入循环的时候不端创建StringBuilder对象,这样反倒是有增加内存开支的嫌疑。所以如果以上假设都成立的话,在使用到字符串拼接的时候,干脆使用StringBuilder 的方式不是更好么?省的转换成StringBuilder的方式后还得在每次循环中不断的创建StringBuilder对象。
3. equals 和 “==”的区别
简单的说,String的 equals()方法比较字符串对象中的字符, == 运算符比较的是两个对象是否引用同一实例,代码如下:
1 String s1 = "Hello";2 String s2 = newString(s1);3 System.out.println(s1.equals(s2)); //True
4 System.out.println(s1==s2); //False
这个代码就比较简单了,看下面是equals的实现方法
public booleanequals(Object anObject) {if (this == anObject) { //判断是否同一对象
return true;
}if (anObject instanceofString) {
String anotherString= (String)anObject;//String类型
int n =count;//一个字符一个字符的比较
if (n ==anotherString.count) {char v1[] =value;char v2[] =anotherString.value;int i =offset;int j =anotherString.offset;while (n-- != 0) {if (v1[i++] != v2[j++])return false;
}return true;
}
}return false;
}
从源码中看到了两个事情:
1. 如果equals对比的是两个对象的话,那equals 和 == 是同样的判断逻辑
2. 只有当判断出都是String类型的对象的时候,才会去对比每个字符是否相等。
看源码是个好习惯,要有耐心。