final關(guān)鍵字(最終)
final修飾的類無法被繼承.
final修飾的方法無法被覆蓋.
final修飾的局部變量,一旦賦值笨枯,不可再改變.
class A{
public void m1(){
//聲明
final int i;
//第一次賦值
i = 100;
//不能重新賦值
i = 1200;
}}
final修飾的成員變量必須“顯示的”初始化.
class A{
//final修飾的成員變量必須手動(dòng)初始化.
final int i = 100;
//成員
final int k;
//Constructor
A(){
k = 200;
}}
//常量.java規(guī)范中要求所有的常量“大寫”
//常量:值不可再改變的變量.
public static final double PI = 3.14;
深入final
final修飾的引用類型撩独,該引用不可再重新指向其他的java對象夕凝。
但是fianl修飾的引用,該引用指向的對象的屬性是可以修改的奏寨。
public static void main(String[] args){
final Customer c = new Customer("JACK",15);
//c是final的椎咧,無法重新賦值忍法。
//c = new Customer("LUCY",20);//Error
c.name = "李四";
c.age = 25;
System.out.println(c.name);
System.out.println(c.age);
}
(String)java.lang.String;是字符串類型真慢。
1.字符串一旦創(chuàng)建不可再改變毅臊。"abc"字符串對象一旦創(chuàng)建理茎,不可再改變成"abcd"
2.提升字符串的訪問效率:在程序中使用了“緩存”技術(shù)黑界。所以在java中所有使用“雙引號”括起來
的字符串都會(huì)在“字符串常量池”中創(chuàng)建一份。字符串常量池在方法區(qū)中被存儲(chǔ)皂林。
3.在程序執(zhí)行過程中朗鸠,如果程序用到某個(gè)字符串,例如"abc",那么程序會(huì)在字符串常量池
中去搜索該字符串础倍,如果沒有找到則在字符串常量池中新建一個(gè)"abc"字符串烛占,如果找到
就直接拿過來用。(字符串常量池是一個(gè)緩存區(qū)沟启,為了提高訪問字符串的效率)
//創(chuàng)建一個(gè)"abc"字符串對象忆家,該對象的內(nèi)存地址,讓s1變量保存德迹。
//s1是一個(gè)引用芽卿,s1指向 "abc" 對象.
String s1 = "abc";
//可以讓s1重新指向嗎?s1是局部變量,s1前邊沒有final胳搞,所以s1可以重新指向卸例。
//但是"def"字符串本身不可變.
s1 = "def";
String s2 = "Hello"; //在字符串常量池中新建一個(gè)"Hello"字符串對象称杨,該對象不可變
String s3 = "Hello"; //從字符串常量池中直接拿來用。
System.out.println(s2==s3); //true
//比較兩個(gè)字符串是否相等筷转,不能用"=="
String s4 = new String("abc");
String s5 = new String("abc");
System.out.println(s4==s5); //false
//比較兩個(gè)字符串是否一致姑原,必須使用String類提供的equals方法.
System.out.println(s4.equals(s5)); //true
//以下程序執(zhí)行結(jié)束之后,會(huì)在字符串常量池中創(chuàng)建3個(gè)字符串對象
//"aaa" "bbb"? "aaabbb"
String s6 = "aaa";
String s7 = "bbb";
String s8 = s6 + s7;
字符串對象的區(qū)別
1.String s1 = "abc"; 只會(huì)在字符串常量池中創(chuàng)建一個(gè)"abc"字符串對象.
2.String s2 = new String("hello"); 會(huì)在字符串常量池中創(chuàng)建一個(gè)"hello"字符串對象,并且會(huì)在堆中再創(chuàng)建一個(gè)字符串對象呜舒。
第二種方式比較浪費(fèi)內(nèi)存锭汛,常用的是第一種方式。
面試題
//判斷以下程序創(chuàng)建了幾個(gè)對象袭蝗? 3個(gè)
//堆中2個(gè)
//方法區(qū)字符串常量池中1個(gè).
String s1 = new String("Hello");
String s2 = new String("Hello");
使用String的時(shí)候我們應(yīng)該注意的問題:盡量不要做字符串頻繁的拼接操作店乐。
因?yàn)樽址坏﹦?chuàng)建不可改變,只要頻繁拼接呻袭,就會(huì)在字符串常量池中創(chuàng)建
大量的字符串對象眨八,給垃圾回收帶來問題。
String[] ins = {"sport","music","food","sleep"};
//要求將上面的興趣愛好拼接成一個(gè)字符串“sport,music,food,sleep”
String temp = "";
for(int i=0;ins.length; I++){
if(i==ins.length-1){
temp += ins[i];
}else{
temp += ins[i] + ",";
}
}
System.out.println(temp);
字符串常用構(gòu)造方法
//1.String s1 = "abc";
//2.String s2 = new String("abc");
//3.byte[] bytes = {97,98,99,100};
String s3 = new String(bytes);
System.out.println(s3); //abcd? String已經(jīng)重寫了Object中的toString
//4.String s4 = new String(bytes,1,2);
System.out.println(s4); //bc
//5.char[] c1 = {'我','是','中','國','人'};
String s5 = new String(c1);
System.out.println(s5); //我是中國人
//6.String s6 = new String(c1,2,2);
System.out.println(s6); //中國
字符串常用的方法
//1.char charAt(int index);返回指定索引處的char值
String s1 = "我是王勇左电,是壞人廉侧!";
char c1 = s1.charAt(2);System.out.println(c1); //王
//2.boolean endsWith(String endStr);此字符串是否以指定的后綴結(jié)束
System.out.println("HelloWorld.java".endsWith("java")); //true
System.out.println("HelloWorld.java".endsWith("txt")); //false
//3. boolean equalsIgnoreCase(String anotherString);將一個(gè)Str和另一個(gè)str比較,不考慮大小寫
System.out.println("abc".equalsIgnoreCase("ABc")); //true
//4.byte[] getBytes();將字符串轉(zhuǎn)換為byte數(shù)組
byte[] bytes = "abc".getBytes()
//5.int indexOf(String str);判斷此字符串在另一個(gè)字符串第一次出現(xiàn)的索引
System.out.println("http://192.168.1.100:8080/oa/login.action?username=jack&pwd=123".indexOf("/oa"));//25
//6.int indexOf(String str, int fromIndex); 判斷此字符串在另一個(gè)字符串第一次出現(xiàn)的索引篓足,從指定索引開始段誊,
System.out.println("javaoraclec++javavb".indexOf("java",1)); //13
isEmpty()當(dāng)且僅當(dāng)length()為0時(shí)返回true
//7.int lastIndexOf(String str)返回此字符串在此字符串中最右邊出現(xiàn)的索引
System.out.println("javaoraclec++javavb".lastIndexOf("java")); //13
//8.int lastIndexOf(String str, int fromIndex)從指定的索引反向搜索
System.out.println("javaoraclec++javavb".lastIndexOf("java",14)); //13
//9.int length();
System.out.println("abc".length()); //數(shù)組是length屬性,String是length()方法
//10. String replaceAll(String s1,String s2);替換,把java替換成mysql
System.out.println("javaoraclec++javavb".replaceAll("java","mysql")); //這個(gè)程序是4個(gè)字符串//mysqloraclec++mysqlvb
//11.String[] split(String s);
String myTime = "2008,08,08";
String[] ymd = myTime.split(",");以逗號分隔
for(int i=0;ymd.length;i ++){
System.out.println(imd[I]);
}
//12.boolean startsWith(String s);測試此字符串是否以指定的前綴開始
System.out.println("/system/login.action".startsWith("/")); //true
//13.String substring(int begin);截取字符串
System.out.println("/oa/login.action".substring(3)); //? /login.action
//14. String substring(int beginIndex, int endIndex)截取字符串
System.out.println("/oa/login.action".substring(4,9)); //login
//15.char[] toCharArray();將此字符串轉(zhuǎn)換為一個(gè)新的字符串?dāng)?shù)組
char[] c2 = "我是李海波".toCharArray();
//16.轉(zhuǎn)換成大寫
System.out.println("Abcdef".toUpperCase());
//17.轉(zhuǎn)換成小寫
System.out.println("ABCDEf".toLowerCase());
//18.String trim(); 去掉前面空格和后面空格栈拖,但去不掉a后和e前的空格
System.out.print("? ? ? a? bcd e? ? ? ? ? ".trim());
//19.String valueOf(Object obj);返回新的字符串(類型轉(zhuǎn)換)
Object o = null;
System.out.println(o); //不會(huì)连舍,因?yàn)椴⒉皇侵苯诱{(diào)用toString方法,String.valueOf(Object)這個(gè)方法對空值進(jìn)行處理了。
System.out.println(String.valueOf(o));
//System.out.println(o.toString()); //會(huì)出現(xiàn)空指針
java.lang.StringBuffer;
java.lang.StringBuilder;
1.StringBuffer和StringBuilder是什么涩哟?
是一個(gè)字符串緩沖區(qū).
2.工作原理
預(yù)先在內(nèi)存中申請一塊空間索赏,以容納字符序列,
如果預(yù)留的空間不夠用贴彼,則進(jìn)行自動(dòng)擴(kuò)容潜腻,以
容納更多字符序列。
3.StringBuffer,StringBuilder? 和? String最大的區(qū)別器仗?
String是不可變得字符序列融涣,存儲(chǔ)字符串常量池中。
StringBuffer底層是一個(gè)char數(shù)組精钮,但是該char數(shù)組是可變的威鹿。
并且可以自動(dòng)擴(kuò)容。
char中是否可以存儲(chǔ)一個(gè)中文漢字?
解:char底層存儲(chǔ)的是unnicode編碼格式的中文,
只要unnicode編碼中有的中文漢字,就可以在char中聲明
4.StringBuffer和StringBuilder的默認(rèn)初始化容量是16
5.如何優(yōu)化StringBuffer和StringBuilder呢轨香?
最好在創(chuàng)建StringBuffer之前忽你,預(yù)測StringBuffer的存儲(chǔ)字符數(shù)量,
然后再創(chuàng)建StringBuffer的時(shí)候采用指定初始化容量的方式創(chuàng)建StringBuffer.
為了減少底層數(shù)組的拷貝弹沽。提高效率檀夹。
6.StringBuffer和StringBuilder的區(qū)別筋粗?
StringBuffer是線程安全的。(可以在多線程的環(huán)境下使用不會(huì)出現(xiàn)問題.)
StringBuilder是非線程安全的炸渡。(在多線程環(huán)境下使用可能出現(xiàn)問題.)
//創(chuàng)建字符串緩沖區(qū)對象
StringBuffer sb = new StringBuffer(); //16
//可以向StringBuffer中追加字符串.
String[] ins = {"體育","音樂","睡覺","美食"};
//推薦字符串頻繁拼接使用StringBuffer或者StringBuilder
for(int i = 0; I<ins.length;i ++){
if(i==ins.length-1){
sb.append(ins[i]);
}else{
sb.append(ins[i]);
sb.append(",");
}
System.out.println(sb);
}