1. String 是最基本的數(shù)據(jù)類型嗎?
不是垫毙,String是類卡辰,String是不可變的胞皱,對String類的任何改變,都會返回一個新的String類對象九妈。
2. java的八大數(shù)據(jù)類型反砌?
整型:byte,short萌朱,int宴树,long
字符型:char
浮點(diǎn)型:float,double
boolean型:boolean
3. float f=3.4;是否正確晶疼?
不正確酒贬,java內(nèi),整數(shù)默認(rèn)是int冒晰,浮點(diǎn)默認(rèn)是double同衣,支持向上轉(zhuǎn)型,即int自動轉(zhuǎn)long壶运,float自動轉(zhuǎn)double耐齐,但不支持自動向下轉(zhuǎn)型。float f = (float)3.4; float f= 3.4f;都是對的蒋情。
4. short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎埠况?
第一個有錯,還是那句話棵癣,整數(shù)java默認(rèn)是int辕翰。s1是short,1是int狈谊,相加喜命,向上轉(zhuǎn)型是int沟沙,int不能賦值給short,需要強(qiáng)轉(zhuǎn)壁榕。s1 = (short) s1 + 1;
第二個沒錯矛紫,s1 += 1;其實就是s1 = (short) s1 + 1;
5. int和Integer的區(qū)別牌里?
Integer是int的包裝類颊咬,int是基本數(shù)據(jù)類型;Integer默認(rèn)為null牡辽,int默認(rèn)為0喳篇;
用代碼例子說明。
package test;
public class IntTest {
public static void main(String []args) {
Integer a1 = new Integer(100);
Integer a2 = new Integer(100);
Integer b1 = 100;
Integer b2 = 100;
Integer b3 = 128;
Integer b4 = 128;
int c1 = 100;
int c2 = 100;
//false 原因:兩個對象态辛,內(nèi)存地址不同
System.out.println(a1==a2);
//true 原因:非new的Integer比較時麸澜,變量在-128到127之間為true,反之為false
System.out.println(b1==b2);
//false 原因:非new的Integer比較時因妙,變量在-128到127之間為true痰憎,反之為false
System.out.println(b3==b4);
//true
System.out.println(c1==c2);
//false 原因:new Integer()指向堆中新建的對象,
//非new的Integer指向java常量池中的對象攀涵。內(nèi)存地址不同。
System.out.println(a1==b1);
//true 原因:Integer自動拆包洽沟,其實就是int之間的比較
System.out.println(a1==c1);
//true 原因:Integer自動拆包以故,其實就是int之間的比較
System.out.println(b1==c1);
}
}
需要注意的是java在編譯Integer i = 1;時,會變成 Integer i = Integer.valueOf(1);
以下是Integer.valueOf()的源碼
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
也就是說非new的Integer范圍是-128到127之間的數(shù)裆操,會進(jìn)行緩存怒详,下次不會再new,而是直接從緩存里取踪区。
6. 堆(heap),棧(stack),靜態(tài)區(qū)(static area)的分配昆烁?
在網(wǎng)上查完資料之后,總結(jié)如下:
heap區(qū):(存儲的基本單位)
1.保存對象的實例(new創(chuàng)建的對象和數(shù)組)缎岗,實例屬性静尼,屬性類型,對象本身的類型標(biāo)記传泊。
2.存儲的對象包含一個與之對應(yīng)的class信息鼠渺。
3.JVM只有一個heap區(qū),被所有的線程共享眷细。
4.一般人為釋放拦盹,否則程序結(jié)束時由OS回收。
stack區(qū):(運(yùn)行的基本單位)
1.stack區(qū)存對象的引用溪椎,和基礎(chǔ)數(shù)據(jù)類型普舆。
2.保存一個4個字節(jié)的heap內(nèi)存地址恬口,用來定位該對象引用的實例在heap區(qū)的位置。
3.每個線程都有一個stack區(qū)沼侣,互相之間不能訪問楷兽。
靜態(tài)區(qū)/方法區(qū):
1.被所有線程共享。
2.包含所有class和static變量华临。
3.初始化的全局變量和初始化的靜態(tài)變量在一個區(qū)域芯杀,未初始化的全局變量和未初始化的靜態(tài)變量在一個區(qū)域。
7. 最有效率的方法算出2 乘以8?
位運(yùn)算:System.out.println(2<<3);即可雅潭。其實就是2乘(2的三次方)
2的二進(jìn)制往左移兩位揭厚。
2的二進(jìn)制0010,移動之后扶供,1000筛圆。換成十進(jìn)制就是16。
8. System.err.println(i-=i+=i-=i+=i-=i--);怎么算椿浓?
這類題要記住兩點(diǎn)太援,
1、i的值都不會在這串運(yùn)算中改變扳碍。
2提岔、從右往左算。
public static void main(String[] args) {
int i = 5;
//i=i-i+i-i+i-(i-1)
//5-5+5-5+5-4
System.out.println(i-=i+=i-=i+=i-=--i);//1
i = 5;
//i=i-i+i*i+i-(i-1)
//5-5+5*5+5-4
System.out.println(i-=i+=i*=i+=i-=--i);//-30
}
9.兩個對象值相同(x.equals(y) == true)笋敞,但卻可有不同的hash code碱蒙,這句話對不對?
這個本質(zhì)在考 “x和y是兩個對象,x.equals(y)是true的時候夯巷,x和y的hash code一樣嗎赛惩?”
答:不對,因為java中的規(guī)定是——
1)如果兩個對象相同(equals 方法返回 true)趁餐,那么它們的hashCode 值一定要相同喷兼;
2)如果兩個對象的 hashCode 相同,它們并不一定相同后雷。
關(guān)鍵就是搞清楚equals判斷的是什么季惯,看源碼。
public boolean equals(Object obj) {
return (this == obj);
}
那么這里引出來 == 和 equals 的區(qū)別了喷面。
如果是基本變量星瘾,根本沒有equals方法,就是用 == 惧辈,比較的就是內(nèi)容琳状。
如果是new出來的對象,父類是object的這種盒齿,==比較地址念逞,equals也比較地址困食。
如果是java中重寫了equals的類,比較什么就看重寫內(nèi)容了翎承。(一般重寫都是為了比較內(nèi)容)
舉兩個例子硕盹。
1)String中equals源碼
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
2)ArrayList的父類AbstractList的源碼
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator e2 = ((List) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
所以,如果非要實現(xiàn)equals 方法返回 true叨咖,hashCode還不同的情況瘩例,也可以。重寫equals方法甸各。
再舉個例子垛贤。
public class Equals {
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof Equals) {
return true;
}
return false;
}
public static void main(String[] args) {
Equals A = new Equals();
Equals B = new Equals();
System.out.println(A.equals(B) == true);//true
System.out.println(A.hashCode());
System.out.println(B.hashCode());
}
}
10.new String()創(chuàng)建了幾個對象這類問題
首先明白創(chuàng)建了幾個對象就是在說把對象放在了幾個地方。
那么一共就倆地方趣倾,一個是String池聘惦,一個是堆。
然后開始各種String的測試儒恋。
定義String善绎,無非兩種。
1)String s1 = "hello";
2)String s2 = new String("hello");
第一種诫尽,會先驗證String池中有沒有"hello"禀酱,有的話s1指向"hello"。沒有的話創(chuàng)建新的"hello"存入String池中并指向"hello"箱锐。
第二種比勉,會先驗證String池中有沒有"hello",有的話對String池不做任何操作驹止。沒有的話創(chuàng)建新的"hello"并存入String池中。然后繼續(xù)在堆里創(chuàng)建new String("hello")观蜗,并指向它臊恋。
11.當(dāng)一個對象被當(dāng)作參數(shù)傳遞到一個方法后,此方法可改變這個對象的屬性墓捻,并可返回變化后的結(jié)果抖仅,那么這里到底是值傳遞還是引用傳遞?
這個問題,查了資料之后砖第,算是有點(diǎn)想法了撤卢。
一點(diǎn)一點(diǎn)來。
先說結(jié)論:java中沒有引用傳遞梧兼,只有值傳遞放吩。所以這種情況也是值傳遞。
值傳遞的定義是:方法調(diào)用時羽杰,實際參數(shù)把它的值傳遞給對應(yīng)的形式參數(shù)渡紫,方法執(zhí)行中形式參數(shù)值的改變不影響實際參到推。
引用傳遞的定義是:也稱為傳地址。方法調(diào)用時惕澎,實際參數(shù)的引用(地址莉测,而不是參數(shù)的值)被傳遞給方法中相對應(yīng)的形式參數(shù),在方法執(zhí)行中唧喉,對形式參數(shù)的操作實際上就是對實際參數(shù)的操作捣卤,方法執(zhí)行中形式參數(shù)值的改變將會影響實際參數(shù)的值。
看了值傳遞的定義后八孝,有了疑問董朝。
問:“這種情況應(yīng)該不是值傳遞吧?違反了值傳遞的定義呀唆阿,因為對象的屬性變化了益涧。”
答:“對象屬性改了沒問題驯鳖,但是傳遞的參數(shù)并不是對象呀闲询,所以它改不改不違反值傳遞∏痴蓿”
問:“傳遞的參數(shù)不是對象扭弧,那是啥?”
答:“是對象的引用的一個副本记舆「肽恚”
問:“這不還是引用嗎?為啥不是引用傳遞泽腮?”
答:“還是看定義御蒲,引用傳遞 直接傳地址。這種情況傳的引用诊赊,指向地址厚满。所以這是通過傳遞對象引用副本的方式實現(xiàn)了引用傳遞的效果,但是碧磅,它是值傳遞碘箍。”
問:“確定是值傳遞的問題可以了鲸郊,那String對象作為參數(shù)傳遞的話丰榴,為什么沒有返回變化后的結(jié)果呢?”
答:“額秆撮,那照這么說四濒,Integer,Double等也會有此疑問是吧?”
問:“是的峻黍「绰。”
答:“因為,Integer是int的包裝類姆涩,Double是double的包裝類挽拂,String是char[]的包裝類。對包裝類的值操作實際上是通過對其對用的基本類型操作實現(xiàn)的骨饿】髡唬”