主頁 > 後端開發 > 帶你快速看完9.8分神作《Effective Java》—— 例外篇(你真的會用例外嗎?)

帶你快速看完9.8分神作《Effective Java》—— 例外篇(你真的會用例外嗎?)

2022-01-07 07:27:51 後端開發

🍊 Java學習:Java從入門到精通總結

🍊 Spring系列推薦:Spring原始碼決議

📆 最近更新:2022年1月5日

🍊 個人簡介:通信工程本碩💪、阿里新晉猿同學🌕,我的故事充滿機遇、挑戰與翻盤,歡迎關注作者來共飲一杯雞湯

🍊 點贊 👍 收藏 ?留言 📝 都是我最大的動力!

豆瓣評分9.8的圖書《Effective Java》,是當今世界頂尖高手Josh Bloch的著作,在我之前的文章里我也提到過,編程就像練武,既需要外在的武功招式(編程語言、工具、中間件等等),也需要修煉心法(設計模式、原始碼等等)學霸、學神OR開掛,

我也始終有一個觀點:看視頻跟著敲代碼永遠只是入門,從書籍里學到了多少東西才決定了你的上限,

在這里插入圖片描述

我個人在Java領域也已經學習了近5年,在修煉“內功”的方面也通過各種途徑接觸到了一些編程規約,例如阿里巴巴的泰山版規約,在此基礎下讀這本書的時候仍是讓我受到了很大的沖激,學習到了很多約定背后的細節問題,還有一些讓我欣賞此書的點是,書中對于編程規約的解釋讓我感到十分受用,并愿意將他們應用在我的作業中,也提醒了我要把閱讀JDK原始碼的任務提上日程,

最后想分享一下我個人目前的看法,內功修煉不像學習一個新的工具那么簡單,其主旨在于踏實,深入探索底層原理的程序很緩慢并且是艱辛的,但一旦開悟,修為一定會突破瓶頸,達到更高的境界,這遠遠不是我通過一兩篇博客就能學到的東西,

接下來就針對此書列舉一下我的識訓與思考,

不過還是要吐槽一下的是翻譯版屬實讓人一言難盡,有些地方會有誤導的效果,你比如java語言里extends是繼承的關鍵字,書本中全部翻譯成了擴展 就完全不是原來的意思了,所以建議有問題的地方對照英文原版進行語意上的理解,

沒有時間讀原作的同學可以參考我這篇文章,


69 只針對例外的情況才使用例外

try {
	int i = 0;
	while ( true )
		range[i++].climb();
	} catch ( ArrayIndexOutOfBoundsException e ) {
}

當這個回圈企圖訪問陣列邊界之外的第一個陣列元素的時候,使用try-catch并且忽略ArrayIndexOutOfBoundsException例外的手段來達到終止回圈的目的,

對于大多數程式員來說,下面的標準模式可讀性就很高:

for ( Mountain m : range )
	m.climb();

第一串代碼企圖使用Java的錯誤判斷機制來提高程式性能,因為VM對每次陣列訪問都要檢查越界情況,這種想法有三個錯誤:

  1. 因為例外設計的初衷適用于不正常的情形,所有幾乎沒有JVM實作試圖對他們進行優化
  2. 把代碼放在try-catch塊中反而阻止了現代JVM實作本可能執行的某些特定優化
  3. 對資料進行標準的for遍歷并不會導致冗余的檢查

實際上基于例外的模式比標準模式要慢得多


例外應該只用于例外的情況下;他們永遠不應該用于正常的程式控制流程


設計良好的API不應該強迫它的客戶端為了正常的控制流程而使用例外,如果類中具有「狀態相關」(state-dependent)的方法,這個類也應該具有一個單獨的「狀態測驗」(state-testing)方法,即表明是否可以呼叫這個狀態相關的方法,比如Iterator介面含有狀態相關的next方法,以及相應的狀態測驗方法hasNext

for ( Iterator<Foo> i = collection.iterator(); i.hasNext(); ){
	Foo foo = i.next();
	...
}

如果Iterator缺少hasNext方法,客戶端將被迫改用下面的做法:

try {
	Iterator<Foo> i = collection.iterator();
	while ( true ){
		Foo foo = i.next();
		...
	}
} catch ( NoSuchElementException e ) {}

另外一種提供單獨狀態測驗的做法是,如果「狀態相關」方法無法執行想要的計算,就可以讓它回傳一個零?度的optional值,或者回傳一個可識別的null,

  • 如果物件將在缺少外部同步的情況下被并發訪問,或者可被外界改變狀態,就必須使用「optional或者可識別的null」
  • 如果單獨的「狀態測驗」方法必須重復「狀態相關」方法的作業,從性能的?度考慮,就必須使用可被識別的回傳值
  • 其他情況,「狀態測驗」方法優于可被識別的null

70 對可恢復的情況使用受檢例外,對編程錯誤使用運行時例外

Java 程式設計語言提供了三種 throwable:受檢例外(checked exceptions)、運行時例外(runtime exceptions)和錯誤(errors),對于什么情況適合使用哪種 throwable,是有一些一般性的原則提出了強有力的指導:

如果期望呼叫者能夠合理的恢復程式運行,對于這種情況就應該使用受檢例外,通過拋出受檢例外,強迫呼叫者在一個 catch 子句中處理該例外,或者把它傳播出去,因此,方法中宣告要拋出的每個受檢例外都是對 API 用戶的一個潛在提示:與例外相關聯的條件是呼叫這個方法一種可能結果,


運行時例外和錯誤,在行為上兩者是等同的:它們都是不需要也不應該被捕獲的 throwable


用運行時例外來表明編程錯誤,大多數運行時例外都表示 API 的客戶沒有遵守 API 規范建立的約定,例如陣列越界拋ArrayIndexOutOfBoundsException


考慮資源枯竭的情形,這可能是由程式錯誤引起的,比如分配了一塊不合理的過大陣列,也可能確實是由于資源不足而引起的,如果資源枯竭是由于臨時的短缺,或是臨時需求太大造成的,這種情況可能是可恢復的,API 設計者需要判斷這樣的資源枯竭是否允許恢復,如果你相信一種情況可能允許回復,就使用受檢例外;如果不是,則使用運行時例外,如果不清楚是否有可能恢復,最好使用非受檢例外,


好不要實作任何新的 Error 的子類,實作的所有非受檢的 throwable 都應該是RuntimeExceptiond子類,也不應該拋出AssertionError例外,


因為受檢例外往往指明了可恢復的條件,所以對于這樣的例外,提供一些輔助方法尤其重要,通過這種方法呼叫者可以獲得一些有助于程式恢復的資訊,例如,假設因為用戶資金不足,當他企圖購買一張禮品卡時導致失敗,于是拋出受檢例外,這個例外應該提供一個訪問方法,以便允許客戶查詢所缺的費用金額,


71 避免不必要的使用受檢例外

如果呼叫者無法恢復失敗,就應該拋出未受檢例外,如果可以恢復,并且想要迫使呼叫者處理例外的條件,首選應該回傳一個optional值,當且僅當萬一失敗時,這些無法提供足夠的資訊,才應該拋出受檢例外,


受檢例外強迫程式員處理例外的條件,大大增強了可靠性,過分使用受檢例外會使API使用起來非常不方便,如果方法拋出受檢例外,呼叫該方法代碼就必須在catch塊中處理,或者拋出例外,

這種負擔在Java 8中更重了,因為拋出受檢例外的方法不能直接在Stream中使用,


除非下面兩種情況同時成立,否則更適合使用未受檢例外:

  1. 正確地使用API并不能阻止這種例外條件的產生

  2. 一旦產生例外,程式員可以立即采取有效動作


作為一個石蕊測驗,你可以試著問自己:程式員將如何處理該例外,下面的做法是最好的嗎?

} catch ( TheCheckedException e ) {
	throw new AssertionError(); /* Can't happen! */
}

下面這種做法又如何?

} catch ( TheCheckedException e ) {
	e.printStackTrace(); /* Oh well, we lose. */
	System.exit( 1 );
}

如果覺得上面兩種方式都不行的話,還是采用未受檢的例外可能更合適,

石蕊測驗:簡單而具有決定性的測驗

如果方法拋出的受檢例外是唯一的,它給程式員帶來的額外負擔就會非常高:該方法必須放置于一個try塊中,并且不能在Stream里用,


消除受檢例外最容易的方法是,回傳所要的結果型別的一個optional,但缺點是方法無法回傳任何額外的詳細資訊

「把受檢例外變成未受檢例外」的一種方法是,把這個拋出例外的方法分成兩個方法,其中第一個方法回傳一個boolean值,表明是否應該拋出例外,例如:

try {
	obj.action( args );
} catch ( TheCheckedException e ) {
	... /* Handle exceptional condition */
}

被重構為:

if ( obj.actionPermitted( args ) ) {
	obj.action( args );
} else {
	... /* Handle exceptional condition */
}

如果程式員知道呼叫將會成功,或者不介意由于呼叫失敗而導致的執行緒終止,這種重構還允許以下這個更為簡單的呼叫形式:

obj.action(args);

如果物件將在缺少外部同步的情況下被并發訪問,或者可被外界改變狀態,這種重構就是不恰當的,因為在actionPermittedaction這兩個呼叫的時間間隔之中,物件的狀態有可能會發生變化,


72 優先使用標準的例外

Java平臺類別庫提供了一組基本的未受檢例外,它們滿足了絕大多數API的例外拋出需求,

重用標準的例外有多個好處:

  1. 使API更易于學習和使用
  2. 對于用到這些API程式而言,它們的可讀性會更好
  3. 例外類越少,意味著記憶體占用(footprint)就越小,裝載這些類的時間開銷也越少

以下是四種常用的例外:

IllegalArgumentException

  • 當呼叫者傳遞的引數值不合適的時候,往往就會拋出這個例外,比如,假設某一個引數代表了“某個動作的重復次數”,如果程式員給這個引數傳遞了一個負數,就會拋出這個例外,

IllegalStateException

  • 如果因為接收物件的狀態而使呼叫非法,通常就會拋出這個例外,例如,如果在某個物件被正確地初始化之前,呼叫者就企圖使用這個物件,就會拋出這個例外,

ConcurrentModificationException

  • 如果檢測到一個專?設計用于單執行緒的物件,或者與外部同步機制配合使用的物件正在(或已經)被并發地修改,就應該拋出這個例外,

UnsupportedOperationException

  • 如果物件不支持所請求的操作,就會拋出這個例外,
例外使用場合
IllegalArgumentException非null的引數值不正確
IllegalStateException不適合方法呼叫的物件狀態
NullPointerException在禁止使用null的情況下引數值為null
IndexOutOfBoundsExecption下標引數值越界
ConcurrentModificationException在禁止并發修改的情況下,檢測到物件的并發修改
UnsupportedOperationException物件不支持用戶請求的方法

不要直接重用Exception、RuntimeException、Throwable或者Error,對待這些類要像對待抽象類
一樣,


如果希望稍微增加更多的失敗一捕獲(failure-capture)資訊,可以放心地子類化標準例外,但要記住例外是可序列化的


73 拋出與抽象對應的例外

更高層的實作應該捕獲低層的例外,同時拋出可以按照高層抽象進行解釋的例外,這種做法稱為例外轉譯(exception translation),如下代碼所示:

try {
	... /* Use lower-level abstraction to do our bidding */
} catch (LowerLevelException e) {
	throw new HigherLevelException(...);
}

下面的例外轉譯例子取自于AbstractSequentialList類,該類是List介面的一個?架實作(skeletal implementation)

/**
* Returns the element at the specified position in this list.
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()}).
*/
public E get(int index) {
	ListIterator<E> i = listIterator(index);
	try {
		return(i.next() );
	} catch (NoSuchElementException e) {
		throw new IndexOutOfBoundsException("Index: " + index);
	}
}

一種特殊的例外轉譯形式稱為例外鏈(exception chaining),如果低層的例外對于除錯導致高層例外的問題非常有幫助,使用例外鏈就很合適,低層的例外(原因)被傳到高層的例外,高層的例外提供訪問方法(ThrowablegetCause方法)來獲得低層的例外:

// Exception Chaining
try {
	... // Use lower-level abstraction to do our bidding
} catch (LowerLevelException cause) {
	throw new HigherLevelException(cause);
}

高層例外的構造器將原因傳到支持鏈(chaining-aware)的超級構造器,因此它最終將被傳給Throwable的其中一個運行例外鏈的構造器,例如Throwable(Throwable t) :

/* Exception with chaining-aware constructor */
class HigherLevelException extends Exception {
	HigherLevelException( Throwable cause ) {
		super(cause);
	}
}

對于沒有支持鏈的例外,可以利用ThrowableinitCause方法設定原因,例外鏈不僅讓你可以通程序式(用getCause)訪問原因,還可以將原因的堆戰軌跡集成到更高層的例外中,


盡管例外轉譯與不加選擇地從低層傳遞例外的做法相比有所改進,但是也不能濫用它

處理來自底層的例外通常有兩種方法:

  1. (推薦)在呼叫低層方法之前確保它們會成功執行,可以在給低層傳遞引數之前,檢查更高層方法的引數的有效性

  2. 讓更高層來悄悄地處理這些例外,從而將高層方法的呼叫者與低層的問題隔離開來,可以用某種適當的記錄機制(如java.util.logging)將例外記錄下來,這樣有助于管理員調查問題,同時又將客戶端代碼和最終用戶與問題隔離開來,


74 每個方法拋出的例外都需要創建檔案

始終要單獨地宣告受檢例外,并且利用Javadoc@throws標簽,準確地記錄下拋出每個例外的條件

如果一個公有方法可能拋出多個例外類,則不要宣告它會拋出這些例外類的某個超類,


這條有一個例外:main方法它可以被安全地宣告拋出Exception,因為它只通過虛擬機呼叫,


對于方法可能拋出的未受檢例外,如果將這些例外資訊很好地組織成串列檔案,就可以有效地描述出這個方法被成功執行的前提條件,


對于介面中的方法,在檔案中記錄下它可能拋出的未受檢例外顯得尤為重要,這份檔案構成了該介面的通用約定(general contract)的一部分,它指定了該介面的多個實作必須遵循的公共行為,


使用Javadoc@throws標簽記錄下一個方法可能拋出的每個未受檢例外,但是不要使用throws關鍵字將未受檢的例外包含在方法的宣告中


如果一個類中的許多方法出于同樣的原因而拋出同一個例外,在該類的檔案注釋中對這個例外建立檔案,這是可以接受的

一個常?的例子是NullPointerException,若類的檔案注釋中有這樣的描述:「All methods in this class throw a NullPointerException if a null object reference is passed in any parameter」


75 在細節訊息中包含失敗 - 捕獲資訊

當程式由于未被捕獲的例外而失敗的時候,系統會自動地列印出該例外的堆疊軌跡,在堆疊軌跡中包含該例外的字串表示法(string representation),即它的toString方法的呼叫結果,它通常包含該例外的類名,緊隨其后的是細節訊息(detail message),


為了捕獲失敗,例外的細節資訊應該包含“與該例外有關”的所有引數和欄位的值,例如,IndexOutOfBoundsException例外的細節訊息應該包含下界、上界以及沒有落在界內的下標值,


注意兩點:

  1. 在診斷和修正軟體問題的程序中,許多人都可以看?堆疊軌跡,所以千萬不要在細節訊息中包含密碼、密鑰以及類似的資訊

  2. 關于失敗的冗?描述資訊通常是不必要的,這些資訊可以通過閱讀源代碼而獲得,


為了確保在例外的細節訊息中包含足夠的失敗-捕捉資訊,一種辦法是在例外的構造器中引入這些資訊,例如 IndexOutOfBoundsException 中使用如下構造器代替 String 構造器:

/**
* Constructs an IndexOutOfBoundsException.
*
* @param lowerBound the lowest legal index value
* @param upperBound the highest legal index value plus one
* @param index the actual index value
*/
public IndexOutOfBoundsException( int lowerBound, int upperBound, int index ) {
	// Generate a detail message that captures the failure
	super(String.format("Lower bound: %d, Upper bound: %d, Index: %d",lowerBound, upperBound, index ) );
	// Save failure information for programmatic access
	this.lowerBound = lowerBound;
	this.upperBound = upperBound;
	this.index = index;
}

76 保持失敗的原子性

一般而言,失敗的方法呼叫應該使物件保持在被呼叫之前的狀態,具有這種屬性的方法被稱為具有失敗原子性(failure atomic),


有幾種途徑可以實作這種效果:
1. 設計一個不可變的物件

因為當每個物件被創建之后它就處于一致的狀態之中,以后也不會再發生變化,

2. 對于可變物件,在執行操作之前檢查引數的有效性

public Object pop() {
	if ( size == 0 )
		throw new EmptyStackException();
	Object result = elements[--size];
	elements[size] = null; /* Eliminate obsolete reference */
	return(result);
}

3. 調整計算處理程序的順序,使得任何可能會失敗的計算部分都在物件狀態被修改之前發生

TreeMap 的情形為例,它的元素被按照某種特定的順序做了排序,為了向 TreeMap 中添加元素,該元素的型別就必須是可以利用 TreeMap 的排序準則與其他元素進行比較的,如果企圖增加型別不正確的元素,在 tree 以任何方式被修改之前,自然會導致 ClassCastException 例外,

4. 在物件的一份臨時拷貝上執行操作,當操作完成之后再用臨時拷貝中的結果代替物件的內容

5. 撰寫一段恢復代碼(recovery code)

由它來攔截操作程序中發生的失敗,以及便物件回滾到操作開始之前的狀態上,這種辦法主要用于永久性的(基于磁盤的)資料結構,


如果兩個執行緒企圖在沒有適當的同步機制的情況下,并發地修改同一個物件,這個物件就有可能處在在不一致的狀態中,因此,不能在捕獲了ConcurrentModificationException例外之后再假設物件仍然是可用的,錯誤通常是不可恢復的,所以,當方法拋出 AssertionError 時,不需要再去保持失敗原子性,


77 不要忽略例外

要忽略一個例外非常容易,只需將方法呼叫通過try陳述句包圍起來,并包含一個空的catch塊:

try {
	...
} catch ( SomeException e ) {
}

空的catch塊會使例外達不到應有的目的,每當?到空的catch塊時,應該警惕,

有些情形可以忽略例外,比如,關閉FileinputStream 的時候,因為你還沒有改變檔案的狀態,因此不必執行任何恢復動作,即使在這種情況下,把例外記錄下來還是明智的做法,可以調查例外的原因,如果選擇忽略例外,catch塊中應該包含一條注釋,說明為什么可以這么做,并且變數應該命名為ignored

Future<Integer> f = exec.submit(planarMap::chromaticNumber);
int numColors = 4; // Default: guaranteed sufficient for any map
try {
	numColors = f.get( 1L, TimeUnit.SECONDS );
} catch ( TimeoutException | ExecutionException ignored ) {
	// Use default: minimal coloring is desirable, not required
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/404339.html

標籤:java

上一篇:C#落選,Python“連莊”年度編程語言,TIOBE 編程語言排行榜出爐

下一篇:演算法學習筆記 1-1鏈表概述及LeetCode真題圖解(Java)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more