包裝類 基本類型 包裝類 + byte Byte + short Short + int Integer + long Long + char Character + float Float + double Double + boolean Boolean 基本類型轉為包裝類型: + 自動裝箱Au ...
包裝類
- 基本類型-->包裝類
- byte-->Byte
- short-->Short
- int-->Integer
- long-->Long
- char-->Character
- float-->Float
- double-->Double
- boolean-->Boolean
- 基本類型轉為包裝類型:
- 自動裝箱Autoboxing:將基本類型直接賦值給包裝類變數或者Object類變數
- 包裝類型轉為包裝類型:
- 自動拆箱AutoUnboxing:把包裝類對象直接賦值給基本類型變數
- 示例:自動裝箱與自動拆箱
public class T1{
public static void main(String[] args) {
Integer inObj=13; //自動裝箱
Object boolObj=true; //自動裝箱,基本類型賦值給Object類型變數
int i=inObj; //自動拆箱
float f=inObj; //自動拆箱,註意類型匹配
System.out.println(i);
System.out.println(f);
if (boolObj instanceof Boolean) {
boolean b=(Boolean)boolObj; //強制類型轉換+自動拆箱
System.out.println(b);
}
}
}
- 字元串型的值轉為基本類型:
- 用包裝類的靜態的parse...()方法。註意沒有Character類,String的toCharArray()方法轉為字元數組
- 用包裝類的構造器
- 基本類型轉為字元串
- 靜態方法String.valueOf();
- 基本變數+"";
- 示例:字元串轉基本類型
public class Test{
public static void main(String[] args) {
String strByte="127";
String strShort="32767";
String strInt="2147483647";
String strLong="21474836478"; //加了L,用parse和new轉,都會失敗
String strFloat="3.1415F"; //加了F,用parse和new轉,都能成功
String strDouble="3.5665956565";
String strBoolean="true";
byte b1=Byte.parseByte(strByte);
byte b2=new Byte(strByte);
System.out.println(b1+" "+b2);
short s1=Short.parseShort(strShort);
short s2=Short.parseShort(strShort);
System.out.println(s1+" "+s2);
int i1=Integer.parseInt(strInt);
int i2=new Integer(strInt);
System.out.println(i1+" "+i2);
long l1=Long.parseLong(strLong);
long l2=new Long(strLong);
System.out.println(l1+" "+l2);
float f1=Float.parseFloat(strFloat);
float f2=new Float(strFloat);
System.out.println(f1+" "+f2);
double d1=Double.parseDouble(strDouble);
double d2=new Double(strDouble);
System.out.println(d1+" "+d2);
boolean boo1=Boolean.parseBoolean(strBoolean);
boolean boo2=new Boolean(strBoolean);
System.out.println(boo1+" "+boo2);
}
}
輸出
127 127
32767 32767
2147483647 2147483647
21474836478 21474836478
3.1415 3.1415
3.5665956565 3.5665956565
true true
- 示例:基本類型轉字元串
public class Test{
public static void main(String[] args) {
System.out.println(String.valueOf(127));
System.out.println(String.valueOf(32767));
System.out.println(String.valueOf(2147483647));
System.out.println(String.valueOf(21474836478L)); //註意L
System.out.println(String.valueOf(3.1415F)); //註意F
System.out.println(String.valueOf(3.5665956565));
System.out.println(String.valueOf(true));
}
}
輸出如下:
127
32767
2147483647
21474836478 //註意沒有L
3.1415 //註意沒有F
3.5665956565
true
- 包裝類型與基本類型的比較
- 包裝類是引用類型,但可以直接用"=="跟基本類型比較
- 包裝類與包裝類的比較
- 如果包裝類對象都是通過構造方法創建的:遵循對象的比較規則,即用"=="比較的是地址,用equals()比較對象的內容
- 如果包裝類對象都是通過自動裝箱創建,且屬於[-128,127],可以用"=="比較他們的值是否相等;如果在[-128,127]之外,那麼遵循對象的比較規則
- 通過自動裝箱和構造方法創建的對象,不論是不是屬於[-128,127],都遵循對象的比較規則
- 關於[-128,127]:
- Integer類在初始化時,一個內部類的靜態代碼塊將[-128,127]的每個整數都創建了Integer對象,並保存在一個數組中,今後在將[-128,127]中的一個整數自動裝箱成Integer對象時,則直接指向這個數組中對應的對象,因此可以用"=="比較它們的值是否相等
- 示例:包裝類與包裝類的比較
public class Test{
public static void main(String[] args) {
System.out.println(new Integer(2)==new Integer(2));
System.out.println(new Integer(2).equals(new Integer(2)));
Integer i1=127;
Integer i2=127;
System.out.println("127: i1==i2? "+(i1==i2));
Integer i3=128;
Integer i4=128;
System.out.println("128: i3==i4? "+(i3==i4));
Integer i5=new Integer(127);
System.out.println("127: i1==i5? "+(i1==i5));
Integer i6=new Integer(128);
System.out.println("128: i3==i6? "+(i3==i6));
}
}
輸出如下:
false
true
127: i1==i2? true
128: i3==i4? false
127: i1==i5? false
128: i3==i6? false
- 包裝類的compare()方法:compare(a,b)
- a>b:返回1
- a==b:返回0
- a<b:返回-1
- 示例代碼:
public class Test{
public static void main(String[] args) {
System.out.println(Boolean.compare(true,false));
System.out.println(Boolean.compare(new Boolean(false),true));
System.out.println(Integer.compare(5,13));
System.out.println(Integer.compare(new Integer(19),new Integer(10)));
}
}
toString()方法
- Object類的toString()方法返回的是類名@十六進位hashCode()值
- 自己定義一個類的時候,一般都得重寫toString()方法,用以下格式:類名[主要變數1=值1,主要變數2=值2,...]
對象與對象的相等比較equals()與"=="
- "==":
- 對引用變數而言,只有兩個變數指向同一個對象時,才返回true
- 兩個對象如果沒有繼承關係,那麼不能用"=="比較,會出現編譯錯誤
- equals():
- Object的equals()方法跟"=="一樣,指向同一個對象才返回true
- equals()一般都要重寫,重寫應滿足的條件:
- 自反性:對任意x,x.equals(x)一定返回true
- 對稱性:對任意x、y,如果x.equals(y)返回true,那麼y.equals(x)也要返回true
- 傳遞性:對任意x、y、z,x.equals(y)返回true,y.equals(z)也返回true,那麼x.equals(z)一定也返回true
- 一致性:只要兩個對象用於比較的信息沒有發生改變,那麼不論調用equals()多少次,返回的結構都應該相同
- 對任意不是null的x,x.equals(null)一定返回false
- equals()重寫示例,固定寫法
class Person{
private String name;
private String id;
Person(){}
Person(String name,String id){
this.name=name;
this.id=id;
}
public boolean equals(Object obj){
if (this==obj){ //如果二者指向同一個對象,返回true
return true;
}
if (obj!=null && obj.getClass()==Person.class){ //obj不為null,且指向的對象是Person類
Person perObj=(Person)obj; //類型轉換
if(this.id.equals(perObj.id)){ //根據id是否相等判斷兩個Person對象是否相等
return true;
}
}
return false; //如果obj為null或者obj指向的對象不是Person,返回false
}
}
字元串與"=="
- 字元串有兩種情況,一種是字元串直接量,存儲在常量池中,常量池也在堆記憶體中;一種是堆記憶體中的字元串對象,存儲在堆記憶體中
- String的這個問題很複雜,慢慢來看,下麵參考:http://www.cnblogs.com/kkgreen/archive/2011/08/24/2151450.html
代碼1:
String s1="AB";
String s2="A"+"B";
System.out.println(s1==s2); //true。編譯階段即可確定s2="AB",運行時,s1和s2都指向常量池的"AB"
代碼2:
String s1="AB";
String s2="B";
String s3="A"+s2;
System.out.println(s1==s3); //false。s2是變數,編譯階段不能確定s3的值
代碼3:
String s1="AB";
final String s2="B"; //註意多了個final
String s3="A"+s2;
System.out.println(s1==s3); //true。s2的值不可變,編譯階段就確定了s3的值是"AB"
代碼4:
public static void main(String[] args) {
String s1="AB";
final String s2=getString(); //註意有final
String s3="A"+s2;
System.out.println(s1==s3); //false。雖然s2值不可變,但是是通過方法返回的,編譯階段也不能確定其值
}
static String getString(){
return "B";
}
代碼5:
String s1="AB";
String s2="A";
String s3="B";
String s4=s2+s3;
System.out.println(s1==s4); //false.
代碼:6
String s1="AB";
final String s2="A";
final String s3="B";
String s4=s2+s3;
System.out.println(s1==s4); //true.s4的值在編譯期即可確定
代碼7:開始引入intern()方法
String s1="A";
String s2="B";
String s3=s1+s2; //s3實際指向堆記憶體中的"AB"
System.out.println(s3==s3.intern()); //true。s3.intern()將堆記憶體中"AB"對象的地址添加到常量池表中,而不是在常量池中再創建個對象,二者實際都指向堆記憶體中的對象,因此二者相等
System.out.println(s3=="AB"); //true。s3指向堆記憶體中"AB"的地址;"AB"按理說應當位於常量池,但常量池中只保存了"AB"在堆記憶體中的地址,所有二者還是相當
//intern()方法用於將該字元串追加到常量池中,如果已經有了,就返回其引用;如果沒有就將地址添加到常量池表中,再返回其引用,實際指向的是堆記憶體中的對象
代碼8:將代碼7最後兩行代碼換個順序
String s1="A";
String s2="B";
String s3=s1+s2;
System.out.println(s3=="AB"); //false.s3指向堆記憶體中的對象,"AB"則在常量池中
System.out.println(s3==s3.intern()); //false.s3還是指向堆記憶體中的對象,s3.intern()返回常量池中的"AB"的地址
- 總結:
- 代碼7和8的結果十分詭異,以上所做的解釋也只是一種猜測,關鍵在於intern()方法,在常量池中沒有字元串的情況下,是新建個字元串對象,還是將字元串的地址添加在常量池表中
- 凡是編譯階段能確定的字元串,在運行期就在常量池中創建一個運算後的對象,而不會再計算一遍,
這點存疑
,從Java1.7開始,常量池位於堆記憶體 - 用""創建的字元串位於常量池
- 用new String()構造方法創建的字元串位於堆記憶體中,運行期創建
- 用"+"連接的字元串直接量,在編譯器就可以確定連接後的值,因此屬於常量池
- 用"+"連接的是字元串和變數或者方法返回值,則要到運行期才能確定,屬於堆記憶體對象
- 其他:
- String s1=new String("ABC");String s2=new String("ABC");這兩個語句創建了3個String對象