【Java】第一阶段练习题
字符串
如果字符串常量池中存在相同內容的字符串對象的引用,則將這個引用返回。否則新的字符串對象被創建,然后將這個引用放入字符串常量池,并返回該引用。
第三段s1和s2都是以字面量的形式創建,s1首先創建,s2創建的時候會在常量池中找是否相同內容的字符串對象,找到了s1,把s1的引用返回給s2。所以s1和s2的地址是相同的。
凡是String s=“a”+“b”;或者String s=“ab”;產生一個字符串常量在棧中。
第四段【s1+“c”】是調用stringBuffer操作并創建一個String對象也就是說+操作符使用StringBuffer的append方式實現的最后返回一個新創建的String對象,而不是string常量。String s3=s1+“c”;保存在堆中。
凡是字符串變量與字符串變量或者字符串常量之間使用+都會產生一個String對象到堆中。
String類的對象內容不可改變,所以每當進行字符串拼接時,總是會在內存中創建一個新的對象,所以經常改變內容的字符串最好不要用String,因為每次生成對象都會對系統性能產生影響。
StringBuilder又稱為可變字符序列,是JDK5.0中新增加的一個類,它是一個類似于String的字符串緩沖區,通過某些方法調用可以改變該序列的長度和內容。即它是一個容器,容器中可以裝很多字符串,并且能夠對其中的字符串進行各種操作。它的內部擁有一個數組用來存放字符串內容,進行字符串拼接時,直接在數組中加入新內容,StringBuilder會自動維護數組的擴容。
日期
public static void main(String[] args) throws ParseException {//獲取當前的日期,并把這個日期轉換為指定格式的字符串,如2088-08-08 08:08:08。Date d1 = new Date();SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String formatDate1 = sdf1.format(d1);System.out.println(formatDate1);//使用SimpleDateFormat類,把2018-03-04轉換為2018年03月04日。SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");Date d2 = sdf2.parse("2018-03-04");SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");String formatDate2 = sdf3.format(d2);System.out.println(formatDate2);//用程序判斷2018年2月14日是星期幾Calendar c = Calendar.getInstance();c.set(2018,2,14);int week = c.get(Calendar.DAY_OF_WEEK);System.out.println(week);System.out.println(c.get(Calendar.YEAR)+"年"+c.get(Calendar.MONTH)+"月"+c.get(Calendar.DATE)+"日是星期"+(week-1));}集合
集合框架:
list轉為數組,可以調用toArray方法
public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);Object[] o = list.toArray();System.out.println(Arrays.toString(o));}迭代器的實現原理
Iterator it = list.iterator();
首先調用iterator方法獲得一個迭代器對象。然后用hasNext方法判斷是否還有下一個元素,用Next方法獲取下一個元素。
迭代器在遍歷集合的時候,內部采用指針來跟蹤集合中的元素。在調用Next之前,指針指在第一個元素之前,不指向任何元素。每調用一個Next,指針后移一位,并將當前指向元素返回。直到遇到hasNext返回false結果時停止移動指針。
Comparable和Comparator兩個接口的區別
Comparable:強行對實現它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的compareTo方法被稱為它的自然比較方法。只能在類中實現compareTo()一次,不能經常修改類的代碼實現自己想要的排序。實現此接口的對象列表(和數組)可以通過Collections.sort(和Arrays.sort)進行自動排序,對象可以用作有序映射中的鍵或有序集合中的元素,無需指定比較器。
Comparator強行對某個對象進行整體排序。可以將Comparator 傳遞給sort方法(如Collections.sort或 Arrays.sort),從而允許在排序順序上實現精確控制。還可以使用Comparator來控制某些數據結構(如有序set或有序映射)的順序,或者為那些沒有自然順序的對象collection提供排序。
異常
異常的繼承體系
throw與throws的區別
異常處理方式
try-catch-finally:自己定義異常的處理邏輯,處理之后的程序可以繼續運行。try是可能發生異常的部分,catch寫明異常的處理邏輯,finally代碼塊是無論是否發生異常,都必須執行的代碼,用于釋放資源。
throws:在方法聲明處寫上異常類,拋出給調用者進行處理,最后由JVM進行中斷處理。
常見異常和出現原因
- 空指針異常:當應用試圖在要求使用對象的地方使用了null時,拋出該異常。
- 數組越界異常:當對數組的索引值為負數或大于等于數組大小時拋出此異常。
- 算數運算異常:除零操作
- 數字格式異常:當試圖將一個String轉換為指定的數字類型,而該字符串并不滿足數字類型要求的格式時,拋出該異常。
并發和并行的區別
并行:指兩個或多個事件在同一時刻發生(同時發生)。
并發:指兩個或多個事件在同一個時間段內發生。(不同時)
進程和線程的區別
進程指正在運行的程序。確切的來說,當一個程序進入內存運行,即變成一個進程,進程是處于運行過程中的程序,并且具有一定獨立功能。
線程是進程中的一個執行單元,負責當前進程中程序的執行,一個進程中至少有一個線程。一個進程中是可以有多個線程的,這個應用程序也可以稱之為多線程程序。
一個程序運行后至少有一個進程,一個進程中可以包含多個線程,但一個進程中至少包含一個線程。比如使用迅雷軟件下載網絡文件時,同時下載多個文件,就使用到了多線程下載。
自定義異常
public class NoScoreExcpetion extends Exception {public NoScoreExcpetion() {}public NoScoreExcpetion(String message) {super(message);} } public class Student {private String name;private int id;private int score; ...... //其他方法省略 ......public void setScore(int score) throws NoScoreExcpetion {if(score <= 0){throw new NoScoreExcpetion("成績必須大0");}this.score = score;} } public class Test {public static void main(String[] args) throws NoScoreExcpetion {Student s1 = new Student();s1.setName("張三");s1.setId(1);s1.setScore(-100);System.out.println(s1);} }多線程
創建多線程對象,開啟多線程。
在子線程中輸出1-100之間的偶數,主線程輸出1-100之間的奇數。
start()方法與run()方法的區別
start開啟線程,讓jvm調用run()方法在開啟的線程中執行。
run不開啟線程,只是對象調用方法
創建線程的兩種方式
繼承Thread:定義線程子類,繼承Tread,重寫run方法。創建線程子類對象,調用start方法開啟線程。
實現Runnable:實現Runnable類,并重寫run方法。創建Runnable實現類對象,傳入Thread對象的含參構造方法中,通過Thread對象調用start方法開啟線程。
public class Test{public static void main(String[] args) {Runnable r = new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}};Thread t = new Thread(r);t.start();System.out.println(Thread.currentThread().getName());} }實現Runnable接口的優勢
- 接口可以多實現,而類只能單繼承
- 適合多個相同的程序代碼的線程去共享同一個資源。
- 增加程序的健壯性,實現解耦操作,代碼可以被多個線程共享,代碼和數據獨立。
- 線程池只能放入實現Runnable或callable類線程,不能直接放入繼承Thread的類。
線程狀態
- new:新建狀態
- blocked:阻塞狀態。當一個線程試圖獲取一個對象鎖,而該對象鎖被其他的線程持有,則該線程進入Blocked狀態;當該線程持有鎖時,該線程將變成Runnable狀態。
- time-waiting:休眠狀態。一個線程在等待另一個線程執行一個(喚醒)動作時,該線程進入Waiting狀態。進入這個狀態后是不能自動喚醒的,必須等待另一個線程調用notify或者notifyAll方法才能夠喚醒。
- waiting:無限等待 。同waiting狀態,有幾個方法有超時參數,調用他們將進入Timed Waiting狀態。這一狀態將一直保持到超時期滿或者接收到喚醒通知。帶有超時參數的常用方法有Thread.sleep 、Object.wait。
- runnable:運行狀態
- terminate:終止狀態
線程池:是一個容納多個線程的容器,里面的線程可以反復拿出來使用,無需反復創建線程對象,而過多消耗系統資源。
線程池的優點:
- 降低資源消耗:減少創建和銷毀線程的次數,可以反復利用線程。
- 提高線程的可管理性:可以根據系統的承受能力,調整線程池中工作線程數目,防止因為消耗過多的內存,而把服務器累趴下(每個線程需要大約1MB內存,線程開的越多,消耗的內存也就越大,最后死機)。
- 提高響應速度:不需要創建線程就可以執行任務。
重寫和重載
重寫是子類對父類的允許訪問的方法的實現過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!
重載是在一個類里面,方法名字相同,而參數不同。返回類型可以相同也可以不同。每個重載的方法(或者構造函數)都必須有一個獨一無二的參數類型列表。
下面的代碼編譯會報錯,因為沒有重寫run方法,run里有參數,不是重寫!
public class Test07 implements Runnable {public static void main(String[] args) {Thread t = new Thread(new Test07());t.start();}public void run(int num) {for (int i = 0; i < num; i++) {System.out.println(i);}} }Lambda
省略規則
- ()內的參數類型可以省略
- ()內如果只有一個參數,()可省略
- {}內如果只有一個語句可以省略{}、return和分號
格式
- ():參數列表
- ->:指向動作
- {}:方法體括號
使用前提
- 必須有接口,且抽象方法唯一。
- 必須可推斷,方法的參數或局部變量類型必須為Lambda對應的接口類型,才能使用Lambda作為該接口的實例。
無參無返回值Lambda練習
給定一個導演 Director接口,內含唯一的抽象方法makeMovie,且無參數、無返回值,使用lambda表達式在Test中完成調用。
有參有返回值Lambda練習
給定一個計算器 Calculator 接口,內含抽象方法 calc (減法),其功能是可以將兩個數字進行相減,并返回差值。使用Lambda表達式在Test中完成調用。
總結
以上是生活随笔為你收集整理的【Java】第一阶段练习题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里-2019算法岗笔试编程题-kmp匹
- 下一篇: 【LeetCode】分类刷题 之 栈和队