国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 Java java教程 4 中最有趣的 Java 錯誤

4 中最有趣的 Java 錯誤

Jan 01, 2025 am 09:19 AM

2024 年,我們分析了大量項目,并在博客上分享我們的發(fā)現(xiàn)?,F(xiàn)在是除夕夜——是時候講喜慶故事了!我們收集了在開源項目中檢測到的最有趣的 Java 錯誤,現(xiàn)在將它們帶給您!

Top most intriguing Java errors in 4

前言

我們長期以來一直秉承發(fā)布 PVS-Studio 檢測到的最有趣的 bug 的傳統(tǒng),但自 2020 年以來就沒有出現(xiàn)與 Java 相關(guān)的置頂!這一次,我嘗試復興復古風格。我希望您手邊有一條舒適的毯子和一杯熱茶,因為我專門為您挑選了 10 多種有趣的昆蟲。以下是他們的排名:

  • 我的個人意見;
  • 該錯誤的有趣背景;
  • 多樣性、可信度和重要性。

準備好用自己的編程智慧來迎接 10 個有趣的故事吧——除夕夜很快就要到來了:)

第10名?;氐轿磥?

第十位,第一個代碼片段張開雙臂歡迎我們。

public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

我忍不住把它放在除夕夜的頂部,因為這段代碼中的一個錯誤可以讓我們更快地到達下一年:)猜猜這個錯誤是從哪里來的?

讓我們看一下傳遞給 SimpleDateFormat 構(gòu)造函數(shù)的參數(shù)??雌饋碛行幔咳绻覀儌鬟f幾乎任何日期,例如撰寫本文的日期 (10/12/2024),代碼將返回正確的值 20241210。

但是,如果我們傳遞 29/12/2024,它將返回 20251229,從而巧妙地提前進入新年。順便說一句,時光倒流也是可行的。

發(fā)生這種情況是因為 SimpleDateFormat 參數(shù)中的 Y 字符代表基于周數(shù)的年份。簡而言之,當一周至少包含新年的四天時,該一周被視為第一周。所以,如果我們的一周從周日開始,我們就可以提前三天進入新的一年。

要修復此問題,只需將大寫 Y 替換為小寫 y 即可。想了解更多嗎?我們專門寫了一整篇文章來討論這個主題。

這是針對此錯誤的 PVS-Studio 警告:

V6122 檢測到使用“Y”(周年)模式:它可能打算使用“y”(年)。 SkeinParameters.java 246

由于周數(shù)的具體情況,因此測試并不是發(fā)現(xiàn)此錯誤的最佳方法。那么為什么這樣一個話題性的錯誤會出現(xiàn)在最后呢?原因是該警告不是來自 Bouncy Castle 的實際版本,而是來自我們的測試基地。舊的資源仍然存在,并且這個錯誤已經(jīng)修復了很長時間。這是來自過去的致敬,又是一次時光旅行:)

第9名。 “看來不行”

第九位,我們收到來自 GeoServer 分析的警告:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // ....
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);              // <=
    Assert.assertEquals(newValue, oldValue);
  }
}

這是 PVS-Studio 警告:

V6027 變量“newValue”、“oldValue”通過調(diào)用同一函數(shù)進行初始化。這可能是一個錯誤或未優(yōu)化的代碼。 DataAccessRuleDAOTest.java 110、DataAccessRuleDAOTest.java 111

這樣的錯誤有什么有趣的?讓我來揭示這四個點背后隱藏的是什么:

public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

有評論稱該代碼由于某種原因無法運行。說實話,我第一次看到的時候就笑了。

不過,這個評論相當含糊。測試很可能是故意以這種方式編寫的,以防止在比較失敗時出現(xiàn)故障。然而,該代碼已經(jīng)處于這種狀態(tài)十多年了,這引發(fā)了一些問題。這種模糊性就是我沒有將其排名更高的原因。

第8名。腳中彈

如果我們不能將 JBullet 中的 bug 稱為“搬起石頭砸自己的腳”,我不知道哪些可以這樣稱呼。這是文章中的一個錯誤:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // ....
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);              // <=
    Assert.assertEquals(newValue, oldValue);
  }
}

我認為我們甚至不需要 PVS-Studio 警告來發(fā)現(xiàn)錯誤所在。無論如何,以防萬一,這里是:

V6026 該值已分配給“proxy1”變量。 HashedOverlappingPairCache.java 233

是的,這是一個令人尷尬的簡單錯誤。不過,這種簡單性讓它變得更加搞笑。盡管如此,它還是有自己的故事。

JBullet 庫是 C/C 子彈庫的移植,那里有類似的功能:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // properties equality does not seem to work...
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);
    Assert.assertEquals(newValue, oldValue);
  }
}

很容易看出這段代碼寫得正確。從 gitblame 來看,原來寫的是正確的。原來是代碼從一種語言移植到另一種語言時出現(xiàn)了錯誤。

由于其驚人的樸實加上豐富的歷史,我將這個警告評為第八名。我希望你喜歡這個搬起石頭砸自己腳的 bug 原來是與 C 語言相關(guān)的。

第七名。即使是偉大的數(shù)學家也會犯錯誤

誠然,下一個警告出于多種原因溫暖了我的心。以下是 GeoGebra 檢查的代碼片段:

@Override
public BroadphasePair findPair(BroadphaseProxy proxy0, BroadphaseProxy proxy1) {
  BulletStats.gFindPairs++;
  if (proxy0.getUid() > proxy1.getUid()) {
    BroadphaseProxy tmp = proxy0;
    proxy0 = proxy1;
    proxy1 = proxy0;
  }
  ....
}

嘗試自己找出錯誤!為了不讓你們偷看,我把警告和解釋隱藏在劇透里了。

答案
首先,我們看一下PVS-Studio的警告:

V6107 正在使用常量 0.7071067811865。結(jié)果值可能不準確??紤]使用 Math.sqrt(0.5)。 DrawAngle.java 303

事實上,0.7071067811865 并不是什么神奇的數(shù)字——它只是 0.5 平方根的四舍五入結(jié)果。但這種精度損失有多嚴重呢? GeoGebra 是一款為數(shù)學家量身定制的軟件,額外的精度似乎并沒有什么壞處。

為什么我這么喜歡這個bug?

首先,在會議上,我經(jīng)常要求與會者在其他代碼片段中找到類似的錯誤。當錯誤隱藏在常量中時,看著他們仔細分析代碼總是很有趣。

其次,這是我為 Java 分析器實現(xiàn)的第一個診斷規(guī)則。這就是為什么我無法抗拒將它放在頂部的原因——即使意識到了偏見——我把它放在第七位:)

第六名。這個模式不起作用

以下警告是我從基于 DBeaver 檢查的第一篇文章中獲取的,可能不會立即引起我們的注意。這是一個代碼片段:

public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

以下是 PVS-Studio 分析器檢測到的內(nèi)容:

V6082 不安全的雙重檢查鎖定。該字段應(yīng)聲明為易失性的。 TaskImpl.java 59、TaskImpl.java317

雖然這個特定的警告沒有什么特別的,但我仍然覺得它非常有趣。關(guān)鍵是所應(yīng)用的雙重檢查鎖定模式不起作用。有什么竅門呢?這在 20 年前是相關(guān)的:)

如果您想了解有關(guān)該主題的更多信息,我建議您閱讀全文。但現(xiàn)在,讓我給您一個快速總結(jié)。

雙重檢查鎖定模式用于在多線程環(huán)境中實現(xiàn)延遲初始化。在“重量級”檢查之前,會在沒有同步塊的情況下執(zhí)行“輕量級”檢查。僅當兩項檢查都通過時才會創(chuàng)建資源。

但是,在這種方法中,對象創(chuàng)建是非原子,并且處理器和編譯器可以更改操作順序。因此,另一個線程可能會意外收到部分創(chuàng)建的對象并開始使用它,這可能會導致不正確的行為。這個錯誤可能很少發(fā)生,因此調(diào)試對于開發(fā)人員來說將是一個巨大的挑戰(zhàn)。

這里有一個變化:這種模式直到 JDK 5 才起作用。從 JDK 5 開始,由于 happens-before 原則,引入了 volatile 關(guān)鍵字來解決重新排序操作的潛在問題。分析器警告我們應(yīng)該添加此關(guān)鍵字。

但是,無論如何,最好避免這種模式。從那時起,硬件和 JVM 性能已經(jīng)取得了長足的進步,并且同步操作不再那么慢了。然而,不正確地實現(xiàn) DCL 模式仍然是一個常見的陷阱,可能會產(chǎn)生上述的嚴重后果。這證實了我們的分析器在舊項目中仍然發(fā)現(xiàn)此類疏忽錯誤的事實。

第5名。微觀優(yōu)化

第五名是另一個 DBeaver 警告,我們專門寫了一篇文章。我們來看看:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // ....
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);              // <=
    Assert.assertEquals(newValue, oldValue);
  }
}

這里有一個解釋:

V6030 無論左側(cè)操作數(shù)的值如何,都會調(diào)用“&”運算符右側(cè)的方法。也許,最好使用“&&”。 ExasolTableColumnManager.java 79、DB2TableColumnManager.java 77

開發(fā)人員將邏輯 && 與按位 & 混淆了。它們具有不同的行為:表達式中的條件在按位 AND 之后不會終止。 短路求值 不適用于按位 AND。因此,即使 exasolTableBase != null 將返回 false,執(zhí)行線程也會到達 exasolTableBase.getClass() 并導致 NPE。

好吧,這只是一個錯字,讓我們繼續(xù)吧,好嗎? DBeaver 有很多這樣的警告。很多。許多都是相對無害的,但對于好奇的讀者,我在下面留下了一些例子:

使用不會導致錯誤的按位運算
ExasolSecurityPolicy.java:
public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

ExasolConnectionManager.java:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // ....
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);              // <=
    Assert.assertEquals(newValue, oldValue);
  }
}

ExasolDataSource.java:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // properties equality does not seem to work...
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);
    Assert.assertEquals(newValue, oldValue);
  }
}

深入挖掘后,我的團隊假設(shè)開發(fā)人員可能一直在嘗試對性能進行微觀優(yōu)化。想了解完整情況,你可以看看我們的文章——這里我總結(jié)一下。

關(guān)鍵點是按位運算不依賴于分支預測,與邏輯運算相比,可能允許更快的執(zhí)行。

令我們驚訝的是,一個本土基準測試支持了這一說法:

Top most intriguing Java errors in 4

圖表說明了每種操作類型所需的時間。如果我們相信它,按位運算似乎比邏輯運算快 40%。

我為什么要提出這個話題?強調(diào)潛在微觀優(yōu)化的成本。

首先,開發(fā)人員發(fā)明分支預測是有原因的——放棄它的成本太高。因此,基準測試可能運行得更快,因為值具有正態(tài)分布,而在實際情況下不太可能觀察到。

第二,放棄短路評估機制會導致成本大幅上升。如果我們看一下上面劇透中的第三個示例,我們可以看到最快的 contains 操作并不是一直執(zhí)行而不是立即停止。

第三,我們從本章開始就全權(quán)處理此類錯誤。

總體而言,我發(fā)現(xiàn)微優(yōu)化價格的警示故事足以進入我們的前五名。

第四名。不行的話測試也不會落下

自動化測試通常被認為是防止各種錯誤的最終保障。然而,時不時地,我很想問:“誰自己測試這些測試?”來自 GeoServer 檢查的另一個警告再次證明了這一點。這是一個代碼片段:

@Override
public BroadphasePair findPair(BroadphaseProxy proxy0, BroadphaseProxy proxy1) {
  BulletStats.gFindPairs++;
  if (proxy0.getUid() > proxy1.getUid()) {
    BroadphaseProxy tmp = proxy0;
    proxy0 = proxy1;
    proxy1 = proxy0;
  }
  ....
}

PVS-Studio 警告:

V6060 在驗證“e”引用是否為 null 之前,已使用該引用。 ResourceAccessManagerWCSTest.java 186、ResourceAccessManagerWCSTest.java 193

乍一看,這個警告似乎不是分析器最令人興奮的警告,因為 V6060 經(jīng)常是針對冗余代碼發(fā)出的。然而,我承諾我會根據(jù)他們的吸引力來選擇提名。所以,這個案例遠比看上去有趣。

最初,測試邏輯可能看起來是錯誤的,因為 e 變量是從 catch 運算符獲取的,并且進一步保持不變,因此它永遠不會為 null。我們可以進行雜散編輯,并將 if(e == nul) 條件的 then 分支刪除為無法到達。然而,那是完全錯誤的。你找到竅門了嗎?

關(guān)鍵在于包含異常對象的代碼中多了一個變量,它是一個se。它的值會在循環(huán)體內(nèi)發(fā)生變化。所以,我們很容易猜測,條件中應(yīng)該有se變量,而不是e。

這個錯誤會導致then分支永遠不會被執(zhí)行,所以我們不知道有沒有異常。更糟糕的是,在代碼審查中很難注意到這樣的錯誤,因為變量名稱非常相似。

從這個故事中可以汲取兩個智慧:

  1. 清楚地命名變量,即使在測試中也是如此。不然更容易犯這樣的錯誤;
  2. 測試不足以保證項目質(zhì)量,因為它們也可能包含錯誤。因此,它會在應(yīng)用程序內(nèi)留下漏洞。

由于提供了如此寶貴的課程,我將此警告授予第四名。

第三名。祝各位調(diào)試愉快

前三名獲勝者屬于 NetBeans 檢查的警告。之前的代碼片段比較緊湊,我們看一下比較長的代碼片段:

public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

最后一次,嘗試自己找到錯誤——我會等...

Top most intriguing Java errors in 4

正在尋找?

不錯!那些僅在表達式 iDesc.neighbor != null || 中發(fā)現(xiàn)錯誤的人iDesc.index == iDesc.index,很遺憾,你輸了:)

當然,有一個問題,但對于排名第一的問題來說還不夠有趣。是的,這里有兩個錯誤,我欺騙了你一點。但是沒有一點惡作劇的假期怎么算呢? :)

分析器檢測到此處的 i^i 表達式存在錯誤,并發(fā)出以下警告:

V6001 在“^”運算符的左側(cè)和右側(cè)有相同的子表達式“i”。 LayoutFeeder.java 3897

異或運算沒有任何意義,因為兩個相同值的異或?qū)⑹冀K為零。為了快速回顧一下,這里是 XOR 的真值表:

a b a^b
0 0 0
0 1 1
1 0 1
1 1 0

換句話說,只有當操作數(shù)不同時,運算才為真。我們將擁有相同的所有位,因為值是相同的。

為什么我這么喜歡這個bug?有 i^1 操作,看起來與 i^i 幾乎相同。因此,在代碼審查中很容易錯過這個錯誤,因為我們已經(jīng)在上面看到了正確的 i^1。

我不了解你,但這讓我想起了著名的:

public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

否則,很難解釋它是如何進入代碼的——除非我們用一個簡單的拼寫錯誤來忽略這個無聊的版本。如果您確實發(fā)現(xiàn)了該錯誤,請拍拍自己的背,或者在評論中分享您的偵探技巧:)

第二名。當模式失敗時

我已經(jīng)顯示了第一篇和第三篇 DBeaver 文章中的錯誤,跳過第二篇文章。我糾正了——以下內(nèi)容僅來自第二篇文章。

PVS-Studio 分析器不喜歡從 TextWithOpen 類的構(gòu)造函數(shù)調(diào)用 isBinaryContents,該類在子類中被重寫:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // ....
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);              // <=
    Assert.assertEquals(newValue, oldValue);
  }
}

那又怎樣?它被覆蓋了——不過,沒什么大不了的。這看起來像是代碼味道,沒什么關(guān)鍵的。至少,我以前是這么認為的。我專門寫了一篇文章來闡述我與這個錯誤的斗爭。

TextWithOpen 有很多子類,其中之一就是 TextWithOpenFile。在那里,該方法實際上被重寫,它返回一個超類沒有的字段,而不是 false:

@Test
public void testStore() {
  Properties newProps = dao.toProperties();

  // properties equality does not seem to work...
  Assert.assertEquals(newProps.size(), props.size());
  for (Object key : newProps.keySet()) {
    Object newValue = newProps.get(key);
    Object oldValue = newProps.get(key);
    Assert.assertEquals(newValue, oldValue);
  }
}

還有疑問嗎?這個類的構(gòu)造函數(shù)是什么樣的?

@Override
public BroadphasePair findPair(BroadphaseProxy proxy0, BroadphaseProxy proxy1) {
  BulletStats.gFindPairs++;
  if (proxy0.getUid() > proxy1.getUid()) {
    BroadphaseProxy tmp = proxy0;
    proxy0 = proxy1;
    proxy1 = proxy0;
  }
  ....
}

注意到了嗎?調(diào)用超類構(gòu)造函數(shù)后,將初始化二進制字段。然而,有一個對 isBinaryContents 方法的調(diào)用,它引用了子類字段!

Top most intriguing Java errors in 4

這是 PVS-Studio 警告:

V6052 在“TextWithOpen”父類構(gòu)造函數(shù)中調(diào)用重寫的“isBinaryContents”方法可能會導致使用未初始化的數(shù)據(jù)。檢查字段:二進制。 TextWithOpenFile.java(77), TextWithOpen.java 59

這是一張相當有趣的圖片。乍一看,開發(fā)人員似乎遵循了最佳實踐:避免無法維護的意大利面條式代碼,并嘗試通過模板方法模式實現(xiàn)規(guī)范的 OOP。但是,即使在實現(xiàn)這樣一個簡單的模式時,我們也可能會犯錯誤,這就是所發(fā)生的情況。在我看來,這種(錯誤的)簡單之美是穩(wěn)居第二的。

第一名。一個錯誤抵消了另一個錯誤

高興吧!舞臺第一名!競爭很激烈,但必須做出選擇。經(jīng)過深思熟慮,我決定接受 NetBeans 檢查中的警告。讓我介紹一下最終的代碼片段:

public Builder setPersonalisation(Date date, ....) {
  ....
  final OutputStreamWriter
    out = new OutputStreamWriter(bout, "UTF-8");
  final DateFormat
    format = new SimpleDateFormat("YYYYMMdd");
  out.write(format.format(date));
    ....
}

我確信不可能一眼就能發(fā)現(xiàn)這樣的錯誤——當然,除非你自己犯過這個錯誤。我不會讓您久等的——這是 PVS-Studio 警告:

V6009 緩沖區(qū)容量使用字符值設(shè)置為“47”。最有可能的是,“/”符號應(yīng)該放置在緩沖區(qū)中。忽略UnignoreCommand.java 107

事實上,這個錯誤非常簡單:StringBuilder 構(gòu)造函數(shù)沒有接受 char 的重載。那么調(diào)用什么構(gòu)造函數(shù)呢?開發(fā)者顯然認為會調(diào)用一個接受 String 的重載,然后 StringBuilder 的初始值就是這個斜??杠。

但是,會發(fā)生隱式類型轉(zhuǎn)換,并調(diào)用接受 int 的類型構(gòu)造函數(shù)。在我們的例子中,它代表 StringBuilder 的初始大小。將 char 作為參數(shù)傳遞不會在功能上影響任何內(nèi)容,因為它不會包含在最終字符串中。如果超出初始大小,它只會自行增加,不會導致異?;蚱渌弊饔?。

但是等等,我提到了兩個錯誤,不是嗎?第二個在哪里,它們是如何連接的?為了發(fā)現(xiàn)這一點,我們必須讀入方法體并了解這段代碼的作用。

它生成文件或目錄的絕對路徑。根據(jù)代碼,生成的路徑應(yīng)如下所示:

  • 對于文件:/folder1/file
  • 對于目錄:/folder1/folder/.

代碼看起來非常正確。這就是問題所在。代碼確實可以正常工作:)但是如果我們通過用字符串替換字符來修復錯誤,我們將得到這個而不是正確的結(jié)果:

  • /文件夾1/文件/;
  • /文件夾1/文件夾//

換句話說,我們會在字符串末尾得到一個額外的斜杠。它將位于末尾,因為上面的代碼每次都會將新文本添加到行的開頭。

因此,第二個錯誤是這個斜杠根本作為參數(shù)傳遞給構(gòu)造函數(shù)。但是,我不會低估這樣的錯誤,因為如果有人決定在不檢查的情況下用字符串替換字符,可能會出現(xiàn)問題。

這就是錯誤頂部的第一個位置轉(zhuǎn)到正確工作的代碼的方式。新年奇跡,你期待什么? :)

結(jié)論

我希望您喜歡閱讀我的錯誤故事。如果您有任何特別的故事讓您印象深刻,或者您有調(diào)整排名的建議,請隨時在評論中分享您的想法,我會在下次記住它們:)

如果您對其他語言感興趣,我邀請您在此處查看 2024 年最熱門的 C# 錯誤 - 請繼續(xù)關(guān)注新的熱門錯誤!

所有這些錯誤都是用PVS-Studio分析器檢測到的,最新版本(7.34)剛剛發(fā)布!您可以通過此鏈接嘗試一下。

要繼續(xù)關(guān)注有關(guān)代碼質(zhì)量的新文章,我們邀請您訂閱:

  • PVS-Studio X(推特);
  • 我們的每月文章摘要;

新年快樂!

以上是4 中最有趣的 Java 錯誤的詳細內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻,版權(quán)歸原作者所有,本站不承擔相應(yīng)法律責任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

hashmap和hashtable之間的區(qū)別? hashmap和hashtable之間的區(qū)別? Jun 24, 2025 pm 09:41 PM

HashMap與Hashtable的區(qū)別主要體現(xiàn)在線程安全、null值支持及性能方面。1.線程安全方面,Hashtable是線程安全的,其方法大多為同步方法,而HashMap不做同步處理,非線程安全;2.null值支持上,HashMap允許一個null鍵和多個null值,Hashtable則不允許null鍵或值,否則拋出NullPointerException;3.性能方面,HashMap因無同步機制效率更高,Hashtable因每次操作加鎖性能較低,推薦使用ConcurrentHashMap替

為什么我們需要包裝紙課? 為什么我們需要包裝紙課? Jun 28, 2025 am 01:01 AM

Java使用包裝類是因為基本數(shù)據(jù)類型無法直接參與面向?qū)ο蟛僮?,而實際需求中常需對象形式;1.集合類只能存儲對象,如List利用自動裝箱存儲數(shù)值;2.泛型不支持基本類型,必須使用包裝類作為類型參數(shù);3.包裝類可表示null值,用于區(qū)分未設(shè)置或缺失的數(shù)據(jù);4.包裝類提供字符串轉(zhuǎn)換等實用方法,便于數(shù)據(jù)解析與處理,因此在需要這些特性的場景下,包裝類不可或缺。

什么是接口中的靜態(tài)方法? 什么是接口中的靜態(tài)方法? Jun 24, 2025 pm 10:57 PM

StaticmethodsininterfaceswereintroducedinJava8toallowutilityfunctionswithintheinterfaceitself.BeforeJava8,suchfunctionsrequiredseparatehelperclasses,leadingtodisorganizedcode.Now,staticmethodsprovidethreekeybenefits:1)theyenableutilitymethodsdirectly

JIT編譯器如何優(yōu)化代碼? JIT編譯器如何優(yōu)化代碼? Jun 24, 2025 pm 10:45 PM

JIT編譯器通過方法內(nèi)聯(lián)、熱點檢測與編譯、類型推測與去虛擬化、冗余操作消除四種方式優(yōu)化代碼。1.方法內(nèi)聯(lián)減少調(diào)用開銷,將頻繁調(diào)用的小方法直接插入調(diào)用處;2.熱點檢測識別高頻執(zhí)行代碼并集中優(yōu)化,節(jié)省資源;3.類型推測收集運行時類型信息實現(xiàn)去虛擬化調(diào)用,提升效率;4.冗余操作消除根據(jù)運行數(shù)據(jù)刪除無用計算和檢查,增強性能。

什么是實例初始器塊? 什么是實例初始器塊? Jun 25, 2025 pm 12:21 PM

實例初始化塊在Java中用于在創(chuàng)建對象時運行初始化邏輯,其執(zhí)行先于構(gòu)造函數(shù)。它適用于多個構(gòu)造函數(shù)共享初始化代碼、復雜字段初始化或匿名類初始化場景,與靜態(tài)初始化塊不同的是它每次實例化時都會執(zhí)行,而靜態(tài)初始化塊僅在類加載時運行一次。

什么是工廠模式? 什么是工廠模式? Jun 24, 2025 pm 11:29 PM

工廠模式用于封裝對象創(chuàng)建邏輯,使代碼更靈活、易維護、松耦合。其核心答案是:通過集中管理對象創(chuàng)建邏輯,隱藏實現(xiàn)細節(jié),支持多種相關(guān)對象的創(chuàng)建。具體描述如下:工廠模式將對象創(chuàng)建交給專門的工廠類或方法處理,避免直接使用newClass();適用于多類型相關(guān)對象創(chuàng)建、創(chuàng)建邏輯可能變化、需隱藏實現(xiàn)細節(jié)的場景;例如支付處理器中通過工廠統(tǒng)一創(chuàng)建Stripe、PayPal等實例;其實現(xiàn)包括工廠類根據(jù)輸入?yún)?shù)決定返回的對象,所有對象實現(xiàn)共同接口;常見變體有簡單工廠、工廠方法和抽象工廠,分別適用于不同復雜度的需求。

變量的最終關(guān)鍵字是什么? 變量的最終關(guān)鍵字是什么? Jun 24, 2025 pm 07:29 PM

InJava,thefinalkeywordpreventsavariable’svaluefrombeingchangedafterassignment,butitsbehaviordiffersforprimitivesandobjectreferences.Forprimitivevariables,finalmakesthevalueconstant,asinfinalintMAX_SPEED=100;wherereassignmentcausesanerror.Forobjectref

什么是類型鑄造? 什么是類型鑄造? Jun 24, 2025 pm 11:09 PM

類型轉(zhuǎn)換有兩種:隱式和顯式。1.隱式轉(zhuǎn)換自動發(fā)生,如將int轉(zhuǎn)為double;2.顯式轉(zhuǎn)換需手動操作,如使用(int)myDouble。需要類型轉(zhuǎn)換的情況包括處理用戶輸入、數(shù)學運算或函數(shù)間傳遞不同類型的值時。需要注意的問題有:浮點數(shù)轉(zhuǎn)整數(shù)會截斷小數(shù)部分、大類型轉(zhuǎn)小類型可能導致數(shù)據(jù)丟失、某些語言不允許直接轉(zhuǎn)換特定類型。正確理解語言的轉(zhuǎn)換規(guī)則有助于避免錯誤。

See all articles