未經做者容許,不可轉載,若有錯誤,歡迎指正o( ̄▽ ̄)ojava
建議本身寫個小的測試demo體會一下,下面是個人測試代碼c++
public class Test1 { public static void main(String[] args) { VIP vip = new VIP(); SuperVIP superVIP = new SuperVIP(); Owner owner = new Owner(); //這裏owner對象的custom成員變量所屬的類是兩個VIP類的超類 owner.setCustom(superVIP); owner.settlement(); //custom本質上是一個SuperVIP的對象的引用 Custom custom = owner.getCustom(); //這裏調用的是子類重寫後的方法 custom.buyBook(); //這個num是父類的public成員變量,可是沒法獲取custom的私有成員變量 //private修飾的成員變量只能在同一個類中直接訪問,一般用該類的public方法訪問 System.out.println(custom.num); //System.out.println(custom.getName());也沒法獲取子類的私有成員屬性 SuperVIP superVIP1 = (SuperVIP) custom; //之因此能強制類型轉化是由於custom本質上就是SuperVIP對象引用 //因此說繼承是多態的前提 System.out.println(superVIP1.getName()); } } class Custom { private int money = 50; public int num = 100; public void buyBook() { System.out.println("店主買書不花錢"); } } class VIP extends Custom { public void buyBook() { System.out.println("普通會員買書打八折"); } } class SuperVIP extends Custom { private String name = "我是SVIP"; public void buyBook() { System.out.println("超級會員買書打六折"); } public String getName() { return name; } } class Owner { private Custom custom; public Custom getCustom() { return custom; } public void setCustom(Custom custom) { this.custom = custom; } public void settlement() { custom.buyBook(); } }
對應8個基本數據類型有8個包裝器類,這些類能夠用於新建對應8個基本數據類型的對象,而且有着自動裝箱,拆箱的功能(如:不少時候一些方法的參數時Obj類型的對象,可是咱們直接傳入基本數據類型的參數能夠完成調用),在這些類中還定義了許多靜態方法用於基本數據類型和包裝器類之間的轉換,這裏感受力扣上刷點題應該就會熟悉這些API了程序員
有一種說法:接口其實就是抽象類,極度抽象的抽象類,接口中不能存在非抽象方法,接口中的全部方法必須所有是抽象方法。在接口使用時有如下一些要求:編程
修飾一個方法:該方法能夠被繼承但沒法被重寫ide
修飾一個類:該類爲最終類,沒法被繼承函數
修飾一個基本數據類型:該值爲常量沒法被修改學習
在八位二進制下,原碼左側第一位爲符號位,除符號位外其他位取反爲反碼,反碼+1爲補碼,計算機中以補碼形式存儲數據,其中要注意0的存儲與-128的存儲測試
下面是一個byte型的1左移6位,7位,8位後的結果測試:this
public class Test1 { public static void main(String[] args) { byte test = 1; test <<= 6; System.out.println(test); test = 1; test <<= 7; System.out.println(test); test = 1; test <<= 8; System.out.println(test); //如下兩個是int左移7位和31位,這裏是用於區分的,由於默認是int System.out.println(1<<7); System.out.println(1<<31); } }
異常類是一個樹形的族譜結構,如下兩個異常爲Throwable類的兩個子類.net
try { //可能會拋出異常的代碼 } catch { //對異常進行處理 } finally { //必定會執行的代碼 }
throws關鍵字的做用:
接下來時三種throws的使用狀況
1.下面的代碼是異常拋出方法自己不處理,而且調用者依舊選擇不處理,將其交給JVM中斷程序處理
public class Test1 { public static void main(String[] args) throws Exception { int[] array = {1, 2, 3}; //此時main方法中並未對這個拋出異常對象的方法進行捕獲操做,選擇交給JVM中斷處理程序 test(array, -1); } public static void test(int[] array, int index) throws Exception { if (index < 0 || index >= 3) //這句拋出就必須處理這個異常對象,此時在方法後用throws至關於 //將這個拋出的異常交給方法的調用者main方法處理 throw new Exception("下標越界"); System.out.println(array[index]); } }
2.下面代碼是test方法不處理,調用者main方法選擇本身try-catch捕獲拋出的異常,本身處理
public class Test1 { public static void main(String[] args) { int[] array = {1, 2, 3}; //此時方法調用者main選擇捕獲這個拋出異常的方法 try { test(array, -1); } catch (Exception e) { e.printStackTrace(); } } public static void test(int[] array, int index) throws Exception { if (index < 0 || index >= 3) //這句拋出就必須處理這個異常對象,此時在方法後用throws至關於 //將這個拋出的異常交給方法的調用者main方法處理 throw new Exception("下標越界"); System.out.println(array[index]); } }
3.下面的代碼時test方法選擇本身直接捕獲本身拋出的異常,並進行處理
public class Test1 { public static void main(String[] args) { int[] array = {1, 2, 3}; test(array, -1); } public static void test(int[] array, int index) { if (index < 0 || index >= 3) //此時test本方法直接本身處理本身拋出的異常對象 try { throw new Exception("下標越界"); } catch (Exception e) { e.printStackTrace(); } System.out.println(array[index]); } }
下面是一個例子實現了兩種不一樣的開啓線程的方式
public class Test1 { public static void main(String[] args) { //經過實現接口的方式能夠解耦合 MyRunnable myRunnable = new MyRunnable(); //調用Thread類的構造函數傳入線程須要執行的任務(業務邏輯) Thread thread = new Thread(myRunnable); //開啓線程等待資源分配,而後執行run方法業務 thread.start(); //經過繼承的方式 MyThread myThread = new MyThread(); myThread.start(); for (int i = 0; i < 1000; i++) System.out.println("++++++++++主線程++++++++"); } } class MyRunnable implements Runnable { //Runnable是一個接口,內部只有一個抽象的run方法(表明開啓線程後須要執行的業務邏輯) @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("--------MyRunnable--------"); } } } class MyThread extends Thread { //經過繼承Thread類的方式,因爲Thread類自己就繼承了Runnable接口 // 所以所建立的Thread類的實例內部有run方法 //這裏是重寫父類的run方法,替換爲本身想要執行的任務 @Override public void run() { for (int i = 0; i < 1000; i++) System.out.println("=========MyThread============"); } }
建立——》就緒、就緒《——》運行、運行——》阻塞、阻塞——》就緒、運行——》終止
注意點:在外部調用時,sleep休眠要放在啓動以前;不然就是在內部調用sleep則能夠隨時休眠,下面是一個小的例子
public class Test1 { public static void main(String[] args) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } //下面開啓子線程的代碼也是包含在main主線程中的,因此主線程掛起後 //下面的代碼也沒法繼續執行 MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); } } class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) System.out.println("-----MyRunnable------"); } } class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) System.out.println("++++++++MyThread+++++++++"); } }
這裏我作了一個測試,若是由三個線程:主線程、甲線程、乙線程,在主線程中某個位置調用甲線程.join(),會使得除主線程外的另外兩個線程繼續爭奪CPU的資源,直到甲結束,主線程纔會回到就緒態去競爭CPU的使用權,若是此時乙線程尚未結束(我估計在測試代碼中將乙線程的循環寫的很長),則會繼續與主線程進行CPU資源的競爭
public class Test1 { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); MyThread myThread = new MyThread(); myThread.start(); for (int i = 0; i < 100; i++) { System.out.println(i + "========main========"); if (i == 50) { try { Thread.sleep(2000); myThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000000; i++) System.out.println(i + "-----MyRunnable------"); } } class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) System.out.println(i + "++++++++MyThread+++++++++"); } }
線程禮讓:yield是一個靜態方法,經過調用該方法,是在某個特定的時間點讓線程暫停搶佔CPU資源的行爲,只是暫時的禮讓
線程中斷:不少狀況致使線程中止運行,如線程執行完畢自動中止,線程執行過程當中遇到錯誤拋出異常並中止,或者線程執行過程當中根據需求手動中止,有以下三個實例方法
一些獲取當前線程信息的實例方法:
new SuperType(construction parameters) { inner class methods and data }
其中,SuperType能夠是接口,若是是這樣,內部類就要實現這個接口,Super Type也能夠是一個類,若是是這樣,內部類就要擴展這個類。