* 以下內容是我在準備java面試的時候覺得有用,面試官很可能會問的一些問題 * 內容(除了代碼)詳情來自網路(學習的時候遇到不會的百度的 (*^__^*) ) * 如果大家發現有什麼地方不對,請告訴我。謝啦!!☆⌒(*^-゜)v 1:java的基礎類型 Java語言提供了八種基本語言 boolea ...
* 以下內容是我在準備java面試的時候覺得有用,面試官很可能會問的一些問題
* 內容(除了代碼)詳情來自網路(學習的時候遇到不會的百度的 (*^__^*) )和《java編程思想》
* 如果大家發現有什麼地方不對,請告訴我。謝啦!!☆⌒(*^-゜)v
1:java的基礎類型
Java語言提供了八種基本語言
boolean | char | byte | 8位 |
short | 16位 | ||
int | float | 32位 | |
long | double | 64位 |
註意:String本身就是一個對象而不是基本數據類型,String的變數名是對String類的引用
2:String、StringBuffer、StringBuilder之間的區別
2.1:三者的執行速度: String<StringBuffer<StringBulider
2.2:String是字元串常量,也就是說值是不會改變的,StringBuffer和StringBuilder是字元串變數,是可以對值進行操作的。
public class StringTest { public static void main(String argv[]){ String s = "abc"; s = s+"def"; System.out.println("s="+s);//s=abcdef /* * 我們明明就是改變了String型的變數s的,為什麼說是沒有改變呢? * 其實這是一種欺騙,JVM是這樣解析這段代碼的: * 首先創建對象s,賦予一個abc * 然後再創建一個新的對象s用來執行第二行代碼, * 也就是說我們之前對象s並沒有變化,所以我們說String類型是不可改變的對象了, * 由於這種機制,每當用String操作字元串時,實際上是在不斷的創建新的對象, * 而原來的對象就會變為垃圾被GC回收掉,可想而知這樣執行效率會有多低。 */ } }
2.3:StringBulider和StringBuffer的區別
StringBulider是線程非安全的,StringBuffer是線程安全的。JVM不能保證StringBuilder操作是安全的,雖然他速度快,但可以保證StringBuffer是可以確定操作的。但是因為大多數操作是在單線程環境下完成的,所以大多數情況下建議使用StringBuilder是因為速度問題。
2.4:對三者進行總結:如果操作少量的數據,使用String
單線程操作字元串緩衝區下大量的數據使用StringBulider
多線程操作字元串緩衝區下大量的數據使用StringBuffer
3:類型之間的轉換
public class StringTest { public static void main(String argv[]){ //String轉化為int float double String s = "123"; int i=Integer.parseInt(s); float f = Float.parseFloat(s); double d = Double.parseDouble(s); System.out.println("i="+i+" f="+f+" d="+d); System.out.println(Integer.valueOf(s)); //註意:雖然valueOf也可以將字元串轉化為int等,但是valueOf調用的是parse的方法,返回的是已經封裝的對象,如Integer等 //將int float double轉化為String String s1 = String.valueOf(i); String s2 = String.valueOf(f); String s3 = String.valueOf(d); System.out.println("s1="+s1+" s2="+s2+" s3="+s3); } }
4:日期的用法
4.1:calendar和Date的區別
Date是類,Calendar是抽象類。在JDK1.0中,Date是唯一的代表時間的類,但因為Date不變實現國際化,所以JDK1.1版本開始,推薦使用Calendar類進行時間和日期的處理。
import java.util.Calendar; import java.util.Date; public class DateTest { public static void main(String argv[]){ Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); //Sun Jul 23 10:33:44 CST 2017(解釋:星期天 7月 23號 10點33分44秒 2017年) System.out.println(date); //獲取年月 int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH)+1;//日期是0~11 所以要加1 System.out.println("year="+year+" month="+month);//year=2017 month=7 //獲取日期 int day1 = calendar.get(Calendar.DAY_OF_YEAR);//本年的第204天 int day2 = calendar.get(Calendar.DAY_OF_MONTH);//這個月的第23天 int day3 = calendar.get(Calendar.DAY_OF_WEEK);//本周第一天(每周星期天開始) int day4 = calendar.get(Calendar.DATE); System.out.println("day1="+day1+" day2="+day2+" day3="+day3+" day4="+day4);//day1=204 day2=23 day3=1 day4=23 //獲取時分秒 int hour1 = calendar.get(Calendar.HOUR_OF_DAY); int hour2 = calendar.get(Calendar.HOUR); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); //hour1=10 hour2=10 minute=59 second=26 10點59分26秒 System.out.println("hour1="+hour1+" hour2="+hour2+" minute="+minute+" second="+second); } }
4.2:DateFormat和SimpleDateFormat的區別
DateFormat可以直接使用、但其本身是一個抽象類,可以根據Locate指定的區域得到不同的日期顯示效果。SimpleDateFormat是DateFormat的子類,一般情況下DateFormat類很少直接使用,而都是由SimpleDateFormat類完成。
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class DateTest { public static void main(String argv[]){ Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); DateFormat df1 = DateFormat.getDateInstance(); DateFormat df2 = DateFormat.getDateTimeInstance(); System.out.println(df1.format(date));//2017-7-23 System.out.println(df2.format(date));//2017-7-23 12:18:51 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年mm月dd日"); System.out.println(sdf.format(date));//2017年18月23日 } }
5:集合List Set Map的區別
集合List有序,其中的元素可以重覆。List主要有兩種實現方式ArrayList和LinkedList
import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class ListTest{ public static void main(String[] args) { List<String> addList = new ArrayList<String>(); addList.add("a"); addList.add("b"); addList.add("c"); List<String> list = new ArrayList<String>(); list.add("hello");//添加一個元素 list.addAll(addList);//將集合addList添加到集合list System.out.println(list);//[hello, a, b, c] list.contains("hello");//判斷是否存在這個對象 System.out.println(list.contains("hello"));//true System.out.println(list.get(0));//hello list.remove(2);//移除第三個元素“b” set沒有這個方法 list.remove("a");//移除元素a System.out.println(list);//[hello, c] System.out.println(list);//[hello, a, c] list.removeAll(list);//移除list集合裡面的所有元素 System.out.println(list.size());//0 } }
集合Set無序,其中元素不可以重覆。Set主要有兩種實現方式HashSet和TreeSet
import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class SetTest{ public static void main(String[] args) { List<String> addList = new ArrayList<String>(); addList.add("a"); addList.add("b"); addList.add("c"); Set<String> set = new HashSet<String>(); set.add("g");//添加一個元素 set.addAll(addList);//將集合addList添加到集合set //利用迭代器輸出Set Iterator it = set.iterator(); while(it.hasNext()) System.out.print(it.next()+" ");//a b c g set.remove("c");//刪除對象c System.out.println(set);//[a, b, g] set.contains("g");//判斷是否存在這個對象 System.out.println(set.contains("g"));//true set.removeAll(set);//刪除集合set裡面的全部元素 System.out.println(set.size());//0 System.out.println(set.isEmpty());//true } }
集合Map是一種把鍵對象和值對象映射的集合,每個元素都包含一個鍵和一個值,鍵不允許重覆,但是可以將任意多個鍵獨享映射到一個值對象上。Map主要有兩種實現方式HashMap和TreeMap
6:文件
我對文件非常不熟悉,所以這塊會單獨列出來_(:зゝ∠)_
7:面向對象編程的特性
7.1:封裝
封裝即把對象的屬性饑餓操作結合成為一個獨立的整體,並儘可能的隱藏對象內部實現細節
public class User { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
這是一個典型的封裝案例,user類的屬性id和name都是用private隱藏起來了的,只能通過get和set方法來對屬性進行操作
7.2:抽象
使用了關鍵詞abstract聲明的類叫作“抽象類”。如果一個類里包含了一個或多個抽象方法,類就必須指定成abstract(抽象)。“抽象方法”,屬於一種不完整的方法,只含有一個聲明,沒有方法主體。
public abstract class AbstractTest { public abstract void get(); public String set(){ return "這是一個抽象類"; } }
7.3:繼承
繼承是面向對象最顯著的一個特性。繼承是從已有的類中派生出新的類,新的類能吸收已有類的數據屬性和行為,並能擴展新的能力
public class TestExtends { public static void main(String argv[]){ B b = new B(); b.get(); //測試結果:正在執行子類…… 這是父類 } } class A{ public String toString(){ return "這是父類"; } } class B extends A{ public void get(){ System.out.print("正在執行子類…… "+toString()); } }
7.4:多態
多態可以分成編譯多態(主要體現在重載上面)和運行多態(主要體現在繼承上面)
8:重載和重寫的區別
重載是同一個類裡面有相同名稱不同參數列表的方法
重寫是子類裡面創建一個除了方法體其餘的(方法名,參數列表,返回值)都和父類一樣的方法,覆蓋父類方法
需要註意的是一個重寫的方法不能拋除沒有在基類中定義的非運行時異常,但是它可以拋出沒有在基類中定義的運行時異常
原因:1:就算有運行時異常也是可以通過編譯的,而如果出現非運行時異常就必須進行處理(throws或者try{}catch{})
2:子類重寫父類方法所拋出的一場不能超過父類的範疇
9:介面和抽象類的區別
9.1:抽象類裡面的方法可以有具體實現,但介面裡面所有的方法都是抽象方法。
9.2:抽象類可以有構造器,介面不能有構造器
9.3:抽象方法可以有public、protected和default這些修飾符,但是介面只能使用public修飾符
9.4:抽象方法可以繼承一個類和實現多個介面,介面只可以繼承一個或多個其它介面
10:java存儲數據
10.1:寄存器:最快的存儲區,位於處理器內部,寄存器數量及其有限。所以它根據需求進行分配,不能直接控制。
10.2:堆棧:位於通用RAM(隨機訪問存儲器)中,堆棧指針向下移動,則分配新的記憶體,若向上移動,則釋放記憶體。速度僅次於寄存器。需要註意的是:對象引用存儲於堆棧。
10.3:堆:一種通用記憶體池(也位於RAM區)存放所有的java對象。與堆棧相比的優點:編譯器不需要知道存儲的數據在堆里存活多長時間,因此,在堆里分配存儲有很大的靈活性,new創建的對象都在堆裡面。
10.4:常量存儲:常量通常直接存放在程式代碼內部,這樣做是為了安全,因為他們永不改變。有時候在嵌入系統中,常量本身會與其他部分隔開,所以在這種情況下可以將其存放在ROM(只讀存儲器)中。
10.5:非RAM存儲:如果數據完全存活於程式之外,那麼它不受程式的任何控制,在程式沒有運行的時候也可以存放。這種存儲方式的技巧在於:把對象轉化成可以存放在其他沒媒介上的事物,在需要的時候,可以恢覆成常規的基於RAM的對象。java提供了對輕量級持久化的支持,而諸如JDBC和Hibernate這樣的機制提供了更加複雜的對在資料庫中存儲和讀取對象信息的支持。
11:關係操作符
值得註意的是“==”和“!=”比較的是對象的引用。如果相比較兩個對象的實際內容是否相同,下必須使用所有對象都使用的特殊方法equals,但是這個方法不適用於“基本類型”,“基本類型”直接使用“==”和“!=”就可以了。
public class equalsTest{ public static void main(String[] args) { String s1 = "123"; String s2 = "123"; String s3 = new String("123"); String s4 = new String("123"); System.out.println("s1=s2?"+(s1==s2));//true System.out.println("s1=s3?"+(s1==s3));//false System.out.println("s3=s4?"+(s3==s4));//false System.out.println("s1=s2?"+(s1.equals(s2)));//true System.out.println("s1=s3?"+(s1.equals(s3)));//true System.out.println("s3=s4?"+(s3.equals(s4)));//true } }
12:goto、break、continue
儘管goto是java的保留字,但語言中並沒有使用它(goto的標簽讓程式產生的錯誤越來越多,並且標簽和goto是程式難以分析)java沒有goto然而java也能完成一些類似於跳轉的操作,這與continue和break有關
12.1:一般的break會中斷並跳出當前程式
public class bcTest{ public static void main(String[] args) { for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ System.out.println("i="+i+" j="+j); if(j==1) break; } } } }
結果
i=0 j=0
i=0 j=1
i=1 j=0
i=1 j=1
i=2 j=0
i=2 j=1
12.2:帶標簽的break會中斷並跳出標簽所指迴圈
public class bcTest{ public static void main(String[] args) { BreakTest: for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ System.out.println("i="+i+" j="+j); if(j==1) break BreakTest; } } } }
結果
i=0 j=0
i=0 j=1
12.3:一般的continue會退回最內層迴圈的開頭,並繼續執行
public class bcTest{ public static void main(String[] args) { for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ System.out.println("i="+i+" j="+j); if(j==1) continue; } } } }
結果
i=0 j=0
i=0 j=1
i=0 j=2
i=1 j=0
i=1 j=1
i=1 j=2
i=2 j=0
i=2 j=1
i=2 j=2
12.4:帶標簽的continue會到達標簽所指的位置,並重新進入緊接在哪個標簽後面的迴圈
public class bcTest{ public static void main(String[] args) { ContinueTest: for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ System.out.println("i="+i+" j="+j); if(j==1) continue ContinueTest; } } } }
結果
i=0 j=0
i=0 j=1
i=1 j=0
i=1 j=1
i=2 j=0
i=2 j=1
java的標簽不會造成goto的問題,是因為他們的應用場合已經受到了限制,沒有特別的方式用於改變程式的控制
13:構造器
在java中,通過提供構造函數,類的設計者可確保每個對象都會得到初始值,創建對象的時候,如果其類具有構造器,java就會在用戶有能力操作對象之前自動調用響應的構造器,從而保證了初始化的進行。
如果你寫的類裡面沒有構造器,則編譯器會自動幫你創建一個預設構造器。
14:清理:終結處理和垃圾回收
java有垃圾回收器自動的不定期的回收無用對象占據的記憶體資源。但也有特殊情況,假定你的對象獲取了一塊“特殊”的記憶體區域,由於垃圾回收器只知道釋放那些經由new分配的記憶體,所以它不知道該如何釋放該對象的這塊“特殊”記憶體,為了應對這種情況。java允許在類裡面定義一個名為finalize()的方法。
finalize()方法的工作原理:
一但垃圾回收器準備好釋放對象占用的存儲空間,將首次調用其finalize()方法,並且在下一次垃圾回收動作發生的時候才會真正回收對象占用的記憶體。所以要是你打算使用finalize()就能在垃圾回收時做一些重要的清理工作。需要註意的是Java裡面的對象並不總是被垃圾回收。
使用垃圾回收器的唯一原因是回收程式不再使用記憶體,所以對於與垃圾回收有關的任何行為來說(尤其是finalize()方法)。他們必須同記憶體及其回收有關。
15:數組
編譯器不允許指定數組的大小。現在擁有的只是對數組的一個引用,而且也沒有個數組對象本身分配任何空間。為了給數組創建相應的存儲空間,必須寫初始化表達式。
int [] i1 = new int[5] (數組元素中的基本類型會自動初始化為控制,對於數字和字元來說是0,對於布爾型來說是false)
int [] i2 = {1,2,3,4,5}
16:java訪問許可權修飾詞
本類 本包 子類 外部包
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
未完待續……O(∩_∩)O~~