1. 程式人生 > >黑馬程式設計師--Java基礎面試題整理

黑馬程式設計師--Java基礎面試題整理

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a>、期待與您交流!


Java面試題整理(小妞自己學習過程中整理的重點題目,為面試做準備,還不完整,待續)




程式設計基礎


1.(面試題):
char c1 = 126;
char c2 = 180;
char c3 = 300;
System.out.println(c1);//126
System.out.println(c2);//-76
System.out.println(c3);//44


解釋:180在記憶體中的儲存為00000000 00000000 00000000 10110100(補碼)
可以得到反碼:00000000 00000000 00000000 10110011
原碼:00000000 00000000 00000000 11001100
由於char型別在記憶體中佔一個位元組,所以只擷取最後8位,即:11001100
轉換為十進位制為:-76


300在記憶體中的儲存為:00000000 00000000 00000001 00101100(補碼)
原碼也為:00000000 00000000 00000001 00101100
擷取最後8位:00101100


2.面試題:
short s = 4;
s = s + 5;//編譯失敗,涉及到型別轉換
s+=5;//編譯成功,自動強轉
3.例(面試題):
   byte a=3;
   byte b=4;
   byte c=a+b;
   byte d=3+4;//不會報錯,因為參與運算的是常量,編譯器會先計算值,再看該值是否是左邊能夠表示的範圍。如果是,就不報錯。


這個byte c=a+b;是要報錯的,因為a+b在計算的時候是預設轉換成int型計算的(byte,short,char型別的變數計算時皆會提升為int,而其它型別則按它們自己的型別計算),結果也是int型,此時應對a+b進行byte強制轉換。
另:在強制轉換時應對int用()括起來,不然報錯!
4.面試題
byte b1=3,b2=4,b;
b=b1+b2; 
b=3+4;
哪句是編譯失敗的呢?為什麼呢?


5.最有效率的方式算出2乘以8等於幾?
2<<3
6.對兩個整數變數的值進行互換。
位^運算子
a = a ^ b;
b = a ^ b;
a = a ^ b;
7.面試題。switch語句後面的表示式可以是byte嗎?可以是long嗎?可以是String嗎?
值x:用於和表示式進行匹配的值。


可以是byte,short,int,char
JDK5以後可以是列舉(就業班講,實際上就是一個特殊的類)。
JDK7以後可以是String。


8.
/*
列印九九乘法表:面試題
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
*/
for (int i=1;i<=9 ;i++ )
{
for (int j=1;j<=i ;j++ )
{
System.out.print(j+ "*" + i + "=" +j*i+"\t");//製表符\t
}
System.out.println();
}


面向物件:


1.面向物件的思想:(能舉例說)
A:是一種更符合人們思考習慣的思想。
B:把複雜的事情簡單化了。
C:把我們從執行者變成了指揮者。


舉例:
買電腦。
洗衣,做飯。
旅遊。
把大象裝進冰箱。
2.(面試)類與物件的關係:(掌握)
把事物轉換成類:
A:成員變數
定義在類中,方法外。
B:成員方法
和以前的區別是去掉static。


類:是相關的屬性和行為的集合。是一個抽象的概念。
物件:是某種事物的具體存在,具體的表現形式。


舉例:
類:學生
物件:張三
3.構造程式碼塊


(這個知識點主要是面試用)
作用:給物件進行初始化(或者說是把所有建構函式中共同的內容提取出來)
      物件一建立就執行,而且優先於建構函式執行。new一個執行一次
特點:用於定義不同物件共性的初始化內容。
與建構函式的區別:
構造程式碼塊是給所有物件進行統一初始化;而建構函式是給對應的物件初始化。
class Person
{
private String name;
private int age;
{
System.out.println("person code run");//這就是構造程式碼塊!
}
Person()
{
System.out.println("A:name="+name+",age="+age);//建構函式
}


}


4.
物件的初始化過程(面試).jpg


5.程式碼塊(面試題)
(1)執行順序:
靜態程式碼塊 --> 構造程式碼塊 --> 構造方法
eg.繼承中的執行順序:
父類靜態程式碼塊-->子類靜態程式碼塊-->父類構造程式碼塊-->父類構造方法-->子類構造程式碼塊-->子類構造方法
(2)注意事項:
靜態程式碼塊只執行一次。


6.延遲載入的單例設計模式(懶漢式)










7.繼承
好處:(面試)
A:提高程式碼的複用性。
B:讓類與類之間產生了一個關係,是多型的前提。
繼承的特點:(面試)
A:Java只支援單繼承,不支援多繼承。
為什麼?如果支援多繼承,當多個父類定義了相同功能,但功能內容不同時,不確定要執行哪一個,就會有呼叫不明確的問題。
B:Java支援多層(重)繼承。
8.面試題:方法過載和方法覆蓋的區別
方法重寫是在子父類兩個類中實現的,實現的是方法的覆蓋,兩個方法是完全一樣的;
方法過載是在同一個類中實現的,實現的是方法的並列存在,兩個方法只是名字一樣,而方法引數型別或者引數個數至少有一個不同。


過載:只看同名函式的引數列表
    重寫:子父類方法要一模一樣


9.抽象:
面試題
abstract不能和哪些關鍵字共存。
1)private :因為一個abstract方法需要被重寫,而被private修飾的方法不能重寫,所以不能修飾為private;
 2)final:因為一個abstract方法需要被重寫。而被final修飾的類不能被繼承,被final修飾的方法是不能被重寫的,所以不能同final共存;
    3)static:因為一個方法要是同時被static 和abstract修飾,那麼這個方法就可以類名.方法名 呼叫. 但是此方法是抽象的,呼叫也無意義,所以就導致static 和abstract不能共存.


10.抽象類和介面的關係?(面試題掌握)
面試題必考之題!
抽象類和介面的區別與特點總結.
     1:成員特點
抽象類:
成員變數:可以是變數,也可以是常量。
構造方法:有構造方法。
成員方法:可以是抽象方法,也可以是非抽象方法。

介面:
成員變數:只能是常量。
 預設修飾符:public static final
成員方法:只能是抽象方法。
 預設修飾符:public abstract


     2:關係特點
類與類:
繼承關係,只能單繼承,可以多層繼承。


類與介面:
實現關係,可以單實現,也可以多實現。
還可以在繼承一個類的同時,實現多個介面。


介面與介面:
繼承關係,可以單繼承,也可以多繼承。




     3:設計理念的區別
抽象類被繼承,這個類中定義的是整個繼承體現的共性內容。
體現:is a  //當一個類是另外一個類的一種的時候,就使用繼承.舉例:狗是動物的一種.
介面被實現,這個介面中定義的是整個體現的擴充套件內容。
體現:like a   //當一個類像某個東西的時候,就用實現. 舉例: 中國人學了英語,但是你還是中國人,只不過像老外而已.
     ====>對事物本質的抽取,用抽象類
       對事物拓展功能的抽取,用介面
11.內部類:
1.想通過外部類去訪問內部類,則需要通過外部類物件去建立內部類物件,格式為:
Outer.Inner in = new Outer().new Inner();--->面試用,平時幾乎用不到。


2.方法內部類如果需要訪問所在方法的區域性變數,則此變數必須定義為final型常量。
原因(面試用):區域性變數會在方法呼叫完畢後,立馬消失。而方法內部類中如果有地方使用著區域性變數,
當方法消失後,這個方法區中的內容還沒有消失(隨著類還在堆記憶體中等待垃圾回收器回收),
也就是說這個變數還必須存在。所以,為了延長區域性變數的生命週期,就需加final修飾。




常用API


1.重點問題:
A.(面試題)字串最大特點:一旦被初始化就不可以被改變。
指的是字串在常量池中的值不可改變,但是指向該字串的引用是可以改變的,也就是說這個引用可以改變後指向別的字串。
eg.     String str = "abcd";
      str+="efgh";
System.out.println(str);//輸出結果為abcdefgh
解釋:1."abcd"這個內容在常量池中,不可改變;2."efgh"也在常量池中開闢一個空間,也不可改變;3.再開闢一個空間,存放"abcdefgh",然後指向"abcd"的引用指向了"abcdefgh".
===>另一種型別題(面試題):
基本型別:形式引數改變不影響實際引數;
引用型別:形式引數改變直接影響實際引數。
但是,String是一種特殊的引用型別,它的形式引數的改變不影響實際引數
eg.
public class Test {
public static void main(String[] args) {
String s = "abc";
change(s);
System.out.println(s);//abc
}
public static void change(String s){
s+="hello";
System.out.println(s);//abchello
}
}
B.(面試題)
class StringDemo
{
public static void main(String[] args)
{
String s1 = "abc";//s1是一個類型別變數,"abc"是一個物件。
String s2 = new String("abc");//s1和s2有什麼區別?s1在記憶體中有一個物件,s2在記憶體中有兩個物件。
}
}
String str = new String("abc");和 String str ="abc";有什麼區別嗎?
有區別。前者在記憶體中有兩個記憶體空間,後者只有一個。原因是前者建立物件在堆記憶體中開闢了一個空間,然後又在常量池中給"abc"開闢了一個空間,物件引用指向堆記憶體,堆記憶體指向常量池;後者只在常量池中開闢一個空間儲存"abc",沒有再堆記憶體中開闢空間。
===>與之類似的題目(面試題):常量相加會直接累加,然後在常量池裡面去找有沒有,如果有,就是常量池裡面的值,不會再開闢新的空間儲存;
 而變數則會開闢新的空間。
eg.
public class Test {
public static void main(String[] args) {
String s1 = "a";
String s2 = "b";
String s3 ="ab";
System.out.println(s3==s1+s2);//false
System.out.println(s3=="a"+"b");//true
}
}


集合:
1.ConCurrentModificationException 併發修改異常:
// 建立集合物件
List list = new ArrayList();


// 新增元素
list.add("hello");
list.add("world");
list.add("java");


// 需求:請遍歷集合,判斷其中是否有"hello"這個元素,如果有,就再新增一個元素:"IOS"
Iterator it = list.iterator();
while (it.hasNext()) {
String s = (String) it.next();
if ("hello".equals(s)) {
list.add("IOS");//ConCurrentModificationException 通過迭代器遍歷集合時,不能通過集合去操作。
//有兩個解決辦法 A:ListIterator B:for
//it = list.iterator();// 這樣從原理是可以解決的,但是它會引起另外一個問題。OutOfMemoryError
}
}
System.out.println("list:" + list);




解決辦法:
// 完全通過集合實現
for (int x = 0; x < list.size(); x++) {
String s = (String) list.get(x);
if ("hello".equals(s)) {
list.add("IOS");
}
}
System.out.println("list:"+list);
System.out.println("-----------");


// 遍歷
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
if ("hello".equals(s)) {
lit.add("IOS");
}
}
System.out.println("list:" + list);