String是java中的字符串。String类是不可变的,对String类的任何改变,都是返回一个新的String类对象。String不属于8种基本数据类型,String是一个对象。本文主要具体介绍一下String。
例一:
public class TestString {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
String str3 = "ab";
String str4 = "ab"+"c";
String str5 = str3 + "c";
String str6 = new String(str2);
System.out.println( str1 == str2 );
System.out.println( str1 == str4 );
System.out.println( str1 == str5 );
System.out.println( str1 == str6 );
}
}
答案: True True False False
String str4 = "ab"+"c";
其实就是:String str4 = "abc";
再在常量池中查找这个字符串是否存在,如果存在,则让变量直接引用该字符串。所以 str1 和 str4 引用也是相同的。String是不可变而StringBuffer是可变的,但是这可变与不可变究竟是什么意思呢?如果你能用IDE进行debug的话,你就会发现,String实例化以后所有的属性都是final的,而StringBuffer确不是,这就是可变与不可变。下面引用SCJP的试题来解释一下这个例子: 例二:
public class Test {
public static void stringReplace (String text) {
text = text.replace('j' , 'i');
}
public static void bufferReplace (StringBuffer text) {
text = text.append("C");
}
public static void main (String args[]) {
String textString = new String ("java");
StringBuffer textBuffer = new StringBuffer ("java");
stringReplace (textString);
bufferReplace (textBuffer);
System.out.println (textString + textBuffer);
}
}
答案: javajavaC
解释:String 是不可以变的字符串,StringBuffer 是可变的字符串. 对StringBuffer进行操作,是在原来的对象之上进行改变. 而对String进行操作,是创建新的对象. 假设调用stringReplace方法的参数text的内存地址是0x0001的话,在执行 text = text.replace(‘j’ , ‘i’); 以后,text的内存地址就会变成类似0x0002的地址,但是肯定不再是0x0001了,原因就是String类是final的,任何修改都将创造一个 新的字符串。那么在stringReplace方法里面输出text,就应该是0x0002地址里的内容了,iava。 总结: String:在String类中没有用来改变已有字符串中的某个字符的方法,由于不能改变一个java字符串中的某个单独字符,所以在JDK文档中称String类的对象是不可改变的。然而,不可改变的字符串具有一个很大的优点:编译器可以把字符串设为共享的。
**StringBuffer:**StringBuffer类属于一种辅助类,可预先分配指定长度的内存块建立一个字符串缓冲区。这样使StringBuffer类的append方法追加字符 比 String使用 + 操作符添加字符 到 一个已经存在的字符串后面有效率得多。因为使用 + 操作符每一次将字符添加到一个字符串中去时,字符串对象都需要寻找一个新的内存空间来容纳更大的字符串,这无凝是一个非常消耗时间的操作。添加多个字符也就意味着要一次又一次的对字符串重新分配内存。使用StringBuffer类就避免了这个问题.
StringBuilder:一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
批注1: 堆:由JVM分配的,用于存储对象等数据的区域。 栈:由JVM分配区域,用于保存线程执行的动作和数据引用。栈是一个运行的单位,Java中一个线程就会相应有一个线程栈与之对应。 常量池 :在编译的阶段,在堆中分配出来的一块存储区域,用于存储 显式 的String,float或者integer.例如String str=”abc”; abc这个字符串是显式声明,所以存储在常量池。 常量池拓展阅读:Java常量池详解之一道比较蛋疼的面试题 批注2: Question:将字符串“ABCD”按照规律顺序输出ABCD,ABC,BCD,AB,BC,CD,A,B,C,D。 首先分析字符串规律,理清思路这样处理起来才会得心应手。根据规律可以看出字符串的长度是从4->3->2->1这个大致可以知道分组需要循环4次,然后再看每组的字符串结构,可以通过图例很明显的看出(具体就不用解释了吧,图解释的很详细。。。)
代码:
String str = "ABCD";
int len = str.length();
for (int i = 1; i <= len; i++) {
for (int j = 0; j < i; j++) {
System.out.println(str.substring(j, len-i + j+1));
}
}