java筆記-one(簡記)

1291945816發表於2019-04-26

類的繼承:

  • 1.只能在繼承層次內進行型別轉換
  • 2.在將超類轉換為子類時,應該使用 instanceof 進行檢查(staff[1] instanceof Manager(檢查將staff[1]轉換為 Manager類 檢查 staff是否是右邊的一個例項)) instanceof:判斷其左邊物件是否為其右邊類的例項

抽象類:

  • 包含一個或者多個抽象方法的類本身必須被宣告為抽象的。
  • 可以包含具體的資料和具體方法。
  • 抽象方法充當著佔位的角色,它們的具體實現在子類。
  • 類即使不含抽象方法,也是可以宣告為抽象類。
  • 抽象類不能夠例項化。
  • 可以定義一個抽象類的物件變數,但只能引用非抽象子類的物件 equals方法應滿足一下特性:
  • 1.自反性;
  • 2.對稱性;
  • 3.傳遞性;
  • 4.一致性;
  • 5.對於任意非空引用x,x.equals(x)應該返回false 如果x.equals(y)返回true,那麼x.hashCode()就必須與y.hashCode()具有相同的值 x.toString()的地方可以用""+x替代(x就是x.toString()
自動裝箱與拆箱(做裝箱相反的操作)
  • 自動裝箱:自動將基本的資料型別封裝為物件型別
  • ... 是程式碼的一部分,表示這個方法可以接收任意的數量的物件。
  • 允許將一個陣列傳遞給可變引數方法的最後一個引數 可以將已經存在且最後一個引數是陣列的方法重新定義為可變引數的方法,而不會破壞任何已經存在的程式碼

反射:能夠分析類能力的程式稱為反射(reflective)

反射機制可以用來:

  • 在執行時分析類的能力。
  • 在執行時檢視物件,例如,編寫一個toString方法供所有類使用。
  • 實現通用的陣列操作程式碼。
  • 利用Method物件,這個物件很像C++中的函式指標
  • Class類(物件將表示一個特定類的屬性): 儲存 執行時的型別標識(一個Class物件實際上表示的是一個型別,而這個型別未必一定是一種類。例如,int不是類,但int.class是一個Class型別的物件) 檢查異常:就是編譯器要求你必須處置的異常 非檢查異常:編譯器不要求強制處置的異常

介面:描述類有什麼功能,而不是給出每個類的具體功能的實現

介面中的所有方法自動屬於public

介面絕不能含有例項域,在JAVASE8之前,也不能在介面中實現方法

使用關鍵字“interface”宣告一個介面;使用關鍵字“implements”宣告一個類實現一個介面。

與類的許可權的限制相同,介面的也能被設定為public,static,final,也就是說在介面宣告的變數都會被隱式的提升為“公有的靜態常量”

介面不可以例項化,但是可以引用實現了介面的類的物件;

介面中宣告的方法都是抽象的,並且被自動的設定為public。

介面自身不能夠被構造例項化,但可以通過實現該介面的類的方法進行實現。

實現介面的類若不是抽象類,那麼該類必須實現介面的所有方法。

介面與介面之間也可以實現繼承關係,子介面除擁有父介面的所有方法宣告外,還可以定義新的方法宣告。

如同使用instanceof檢查一個物件是否屬於某個特定類一樣,也可以使用instance檢查一個物件是否實現了某個特定的介面

與建立類的繼承關係一樣,介面也可以被擴充套件,這裡允許多條從具有較高通用性的介面到較高專用性的介面的鏈

儘管每個類只能擁有一個超類,但卻可以實現多個介面。

方法二義性的解決:

  • 1.超類優先。(超類與實現的介面都有相同的方法,介面的方法被忽略)
  • 2.介面衝突。(須覆蓋掉,或在實現介面處選擇二者其一)

回撥:指出某個特定事件發生時應該採取的動作的模式。

簡單的理解(淺拷貝):如果想要為物件創造一個副本,且它們的狀態互不影響,那麼應使用clone(克隆,一個新的物件,但是資料是克隆而來的)而不是引用

淺拷貝:不會克隆物件引用的其他物件,克隆物件後可能還會存在與原物件共享資訊的情況。(如果共享的物件是不可變的,或者是屬於一個不可變的類,物件的生命週期中,子物件一直包含不變的常量,那麼這種共享是安全的)

一般的子物件是可變的,所以應該應設定一個深拷貝的clone以便於完全的複製出獨立的副本

深拷貝:應對例項域的可變類進行另外的克隆。

lambda表示式:是一個可傳遞的程式碼塊,可以在以後執行一次或者多次。(parameters)-> expression(表現形式:引數,→,一個表示式,如果程式碼要完成的計算無法放在一個表示式中,則可以像寫方法一樣,把這些程式碼放在{})

即使lambda表示式沒有引數,依然需要提供空括號,就像無引數一樣。

如果可以推匯出一個lambda表示式的型別,則可以忽略其型別。

如果方法只有一個引數,而這個引數的型別可以推導得出,那麼甚至可以省略小括號。無需指定返回型別,會依據上下文推匯出來。

對於Lambda表示式中的多個引數,如果需要顯示宣告一個引數的型別,那麼必須為所有的引數都宣告型別。

注意:如果一個lambda表示式只在某些分支返回一個值,而在另外一些分支不返回值,這是不合法的。如 (int x) -> {if(x >= 0)return 1;}

函式式介面:對於只有一個抽象方法的介面,需要這種介面的物件時,就可以提供一個lambda表示式。

注意:不能把lambda表示式賦值給型別為Object的變數,Object不是一個函式介面。

lambda表示式由三部分組成:

  • 1)一個程式碼塊
  • 2)引數
  • 3)自由變數的值,這裡指的是非引數而且不在程式碼塊中定義的變數
  • lambda表示式可以捕獲作用域中變數的值(確保捕獲的值是明確定義的,且只能引用值不會改變的變數(如果是在外部改變的,也是不合法的))。
  • 規則:lambda表示式中捕獲的變數必須實際上是最終變數,也就是說變數初始化後不會再為它賦新值。
  • 在一個lambda表示式中使用this關鍵字時,是指建立這個lambda表示式的方法的this引數
使用lambda表示式的重點是延遲執行,原因如下:

1.在一個單獨的執行緒中執行程式碼 2.多次執行程式碼 3.在演算法的適當位置執行程式碼(排序中的比較操作) 4.發生某種情況時執行程式碼(點選了一個按鈕,資料到達) 5.只有在必要的時候才執行程式碼 6.要接受這個lambda表示式,需要選擇(偶爾可能需要提供)一個函式式介面

使用內部類的原因:
  • 內部類方法可以訪問該類定義所在的作用域中的資料,包括私有的資料
  • 內部類可以對同一個包中其他類隱藏起來
  • 當想要定義一個回撥函式且不想編寫大量程式碼時,使用匿名內部類比較便捷

內部類的物件總有一個隱式的引用,指向了建立它的外部類物件。(它是不可見的) 外圍類的引用在構造器中設定(該引用類似於c++的this指標) 外圍類引用的正規語法:OuterClass.this編寫內部物件的構造器:outerObject.new InnerClass(construction parameters) 外部類之外的引用內部類:OuterClass.InnerClass 注意:內部類中宣告的所有靜態域都必須是final;不能有static方法

區域性內部類:

不用public或private訪問說明符進行宣告; 作用域:宣告它的這個塊 優勢:對外部可以完全隱藏起來,外部類中其他的程式碼也無法訪問,可以訪問區域性變數(事實上是final)

匿名內部類:

語法格式: new SuperType(construction parameters) { inner class methods and data } 靜態內部類沒有對生成它的外圍類物件的引用特權。

派生於RuntimeException的異常有以下幾種情況:

  • 錯誤的型別轉換
  • 陣列訪問越界
  • 訪問null指標

不是派生RuntimeException的異常:

  • 試圖在檔案尾部後面讀取資料
  • 試圖開啟一個不存在的檔案
  • 試圖根據給定的字串查詢Class物件,而這個字串表示的類並不存在

應該丟擲異常的情況:

  • 呼叫一個丟擲受查異常的方法
  • 程式執行過程中發現錯誤,並且利用throw語句丟擲一個受查異常
  • 程式出現錯誤,例如,a[-1] = 0會丟擲一個ArrayIndexOutOfBoundException這樣的非受查異常
  • JAVA虛擬機器和執行時庫出現的內部錯誤

不管是否有異常被捕獲,finally子句中的程式碼都被執行; 堆疊軌跡是一個方法呼叫過程的列表,它包含了程式執行過程中方法呼叫的特定位置,如:printStackTrace(訪問堆疊軌跡的文字資訊描述) getStackTrace方法:得到StackTraceElement物件的一個陣列,可以在你的程式中分析這個物件陣列。StackTraceElement類含有能夠獲得檔名和當前執行的程式碼行號的方法,還含有獲得類名和方法名的方法。

使用異常機制的技巧:
  • 異常處理不能代替簡單的測試(捕獲異常會花費更多的時間)且基本規則:只有異常情況下使用異常機制
  • 不要過分細化異常
  • 利用異常層次結構
  • 不要壓制異常
  • 在檢測錯誤的時候,”苛刻“要比放任更好
  • 不要羞於傳遞異常

斷言機制: 允許在測試期間向程式碼插入一些檢查語句,當程式碼釋出時,插入的檢測會自動移除

  • 關鍵字:assert 條件; or assert 條件:表示式;(會對條件進行檢測,第一個會丟擲AssertionError異常,第二個會將表示式傳入AssertionError的構造器,且轉換成一個訊息字串)
  • 注意:斷言失敗是致命的、不可恢復的錯誤;斷言檢查只用於開發和測試階段(故不應該使用斷言向程式的其他部分通告發生了可恢復性對的錯誤或者不應該作為程式向使用者通告問題的手段)

記錄日誌

  1. 優點:
  • 可以很容易地取消全部日誌記錄,或者僅僅取消個別的日誌,而且開啟和關閉也很容易
  • 可以很簡單地禁止日誌記錄的輸出(使得留在程式的開銷很小)
  • 日誌記錄可以被定向到不同的處理器(用於控制檯顯示,用於儲存在檔案)
  • 日誌記錄器和處理器都可以對記錄進行過濾(根據過濾實現器制定標準丟棄無用的記錄項)
  • 日誌記錄可以採用不同的方式格式化
  • 應用程式可以使用多個日誌記錄器,它們使用類似包名的這種具有層次結構的名字
  • 在預設的情況下,日誌系統的配置由配置檔案控制。(如果需要的話,應用程式可以替換這個配置)

2.自己定義定義日誌記錄器:private static final Logger myLogger = Logger.getLogger("com.mycpmpany.myapp")(未被任何變數引用的日誌記錄器可能被垃圾回收,所以要使用一個靜態變數儲存日誌記錄器) 3.日誌記錄器級別:

  • 與包名相比,日誌記錄的層次性更強(父與子之間會共享一些東西)
  • SEVERE
  • WARNING
  • INFO
  • 以下級別最好用來記錄那些有助於診斷但對程式設計師無多大意義的除錯資訊:
  • CONFIG
  • FINE
  • FINER
  • FINEST
  • 預設情況下只記錄前三(可以自己設定:logger.setLevel(Level.FINE),可以使用 Level.ALL or Level.OFF開啟或者關閉所有級別的記錄)
  • 如果要記錄的級別設計為INFO或更低,須更改日誌處理器
  • 可以通過編輯配置檔案來修改日誌系統的各種屬性,配置檔案存在於:jre/lib/logging.properties
  • 要想使用另一個配置檔案,需將 java.util.logging.config.file特性設定為配置檔案的儲存位置且以該命令啟動應用程式: java -Djava.util.logging.config.file=configFile MainClass
  • 修改預設的日誌記錄級別,須編輯配置檔案並修改該命令列:.level = INFO可以通過新增一下內容指定自己的日誌級別:com.mycompany.myapp.level = FINE
  • 若想在控制檯上看到FINE級別的訊息:java.util.logging.ConsoleHandler.level=FINE
  • 本地化:應包含資源包中的本地特定資訊,一個程式可以包含多個資源包(一個用於選單,其他則用於日誌訊息);每個資源包會有一個名字且腰圍每個地區建立一個檔案才能將對映新增至資源包中(可以於類檔案放在一起);
  • 請求日誌記錄器時可以指定資源包:Logger logger = Logger.getLogger(LoggerName,''com.mycompany.logmessages'')
  • 為資源包指定資源包的關鍵字

除錯技巧: 1)在每個類中放置一個單獨的main方法。只需在main中呼叫所有方法,看是否能正常執行。2)日誌代理是一個子類的物件,可以截獲方法的呼叫,並進行日誌記錄,然後呼叫超類中的方法;3)利用Throwable類提供的printStackTrace方法,可以從任何一個異常物件中獲得堆疊情況。(不必要通過捕獲來生成堆疊軌跡,任何位置都可以插入Thread.dumpStack()來獲取堆疊軌跡)

相關文章