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

首頁 Java java教程 4 中最有趣的 Java 錯(cuò)誤

4 中最有趣的 Java 錯(cuò)誤

Jan 01, 2025 am 09:19 AM

2024 年,我們分析了大量項(xiàng)目,並在部落格上分享我們的發(fā)現(xiàn)。現(xiàn)在是除夕夜-是時(shí)候講喜慶故事了!我們收集了在開源專案中檢測到的最有趣的 Java 錯(cuò)誤,現(xiàn)在將它們帶給您!

Top most intriguing Java errors in 4

前言

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

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

準(zhǔn)備好用自己的程式設(shè)計(jì)智慧迎接 10 個(gè)有趣的故事吧——除夕夜很快就要到來了:)

第10名?;氐轿磥?

第十位,第一個(gè)程式碼片段張開雙臂歡迎我們。

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

我忍不住把它放在除夕夜的頂部,因?yàn)檫@段程式碼中的一個(gè)錯(cuò)誤可以讓我們更快地到達(dá)下一年:)猜猜這個(gè)錯(cuò)誤是從哪裡來的?

讓我們來看看傳遞給 SimpleDateFormat 建構(gòu)子的參數(shù)。看起來有效嗎?如果我們幾乎傳遞任何日期,例如撰寫本文的日期 (10/12/2024),程式碼將傳回正確的值 20241210。

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

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

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

這是針對此錯(cuò)誤的 PVS-Studio 警告:

V6122 偵測到使用「Y」(週年)模式:它可能打算使用「y」(年)。 SkeinParameters.java 246

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

第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 變數(shù)「newValue」、「oldValue」透過呼叫相同函數(shù)進(jìn)行初始化。這可能是錯(cuò)誤或未最佳化的程式碼。 DataAccessRuleDAOTest.java 110、DataAccessRuleDAOTest.java 111

這樣的錯(cuò)誤有什麼有趣的?讓我來揭示這四個(gè)點(diǎn)背後隱藏的是什麼:

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

有評論稱該程式碼由於某種原因無法運(yùn)行。說實(shí)話,我第一次看到的時(shí)候就笑了。

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

第8名。腳中彈

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

@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);
  }
}

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

V6026 該值已指派給「proxy1」變數(shù)。 HashedOverlappingPairCache.java 233

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

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 來看,原來寫的是正確的。原來是程式碼從一種語言移植到另一種語言時(shí)出現(xiàn)了錯(cuò)誤。

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

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

誠然,下一個(gè)警告出於多種原因溫暖了我的心。以下是 GeoGebra 檢查的程式碼片段:

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

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

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

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

事實(shí)上,0.7071067811865 並不是什麼神奇的數(shù)字——它只是 0.5 平方根的四捨五入結(jié)果。但這種精度損失有多嚴(yán)重呢? GeoGebra 是一款為數(shù)學(xué)家量身訂製的軟體,額外的精確度似乎並沒有什麼壞處。

為什麼我這麼喜歡這個(gè)bug?

首先,在會議上,我經(jīng)常要求與會者在其他程式碼片段中找到類似的錯(cuò)誤。當(dāng)錯(cuò)誤隱藏在常數(shù)中時(shí),看著他們仔細(xì)分析程式碼總是很有趣。

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

第六名。這個(gè)模式不起作用

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

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

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

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

雙重檢查鎖定模式用於在多執(zhí)行緒環(huán)境中實(shí)現(xiàn)延遲初始化。在「重量級」檢查之前,會在沒有同步區(qū)塊的情況下執(zhí)行「輕量級」檢查。只有當(dāng)兩項(xiàng)檢查都通過時(shí)才會建立資源。

但是,在這種方法中,物件建立是非原子,並且處理器和編譯器可以更改操作順序。因此,另一個(gè)執(zhí)行緒可能會意外收到部分建立的物件並開始使用它,這可能會導(dǎo)致不正確的行為。這個(gè)錯(cuò)誤可能很少發(fā)生,因此調(diào)試對開發(fā)人員來說將是一個(gè)巨大的挑戰(zhàn)。

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

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

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

第五名是另一個(gè) 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);
  }
}

這裡有個(gè)解釋:

V6030 無論左側(cè)運(yùn)算元的值為何,都會呼叫「&」運(yùn)算子右邊的方法。也許,最好使用“&&”。 ExasolTableColumnManager.java 79、DB2TableColumnManager.java 77

開發(fā)人員將邏輯 && 與位元 & 混淆了。它們具有不同的行為:表達(dá)式中的條件在位元 AND 之後不會終止。 短路求值 不適用於位元 AND。因此,即使 exasolTableBase != null 將傳回 false,執(zhí)行緒也會到達(dá) exasolTableBase.getClass() 並導(dǎo)致 NPE。

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

使用不會導(dǎo)致錯(cuò)誤的位元運(yùn)算
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);
  }
}

深入挖掘後,我的團(tuán)隊(duì)假設(shè)開發(fā)人員可能一直在嘗試對效能進(jìn)行微觀最佳化。想了解完整情況,你可以看看我們的文章——這裡我總結(jié)一下。

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

令我們驚訝的是,一個(gè)本土基準(zhǔn)測試支持了這個(gè)說法:

Top most intriguing Java errors in 4

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

我為什麼要提出這個(gè)主題?強(qiáng)調(diào)潛在微觀優(yōu)化的成本。

首先,開發(fā)人員發(fā)明分支預(yù)測是有原因的-放棄它的成本太高。因此,基準(zhǔn)測試可能運(yùn)行得更快,因?yàn)橹稻哂谐B(tài)分佈,而在實(shí)際情況下不太可能觀察到。

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

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

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

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

自動(dòng)化測試通常被認(rèn)為是防止各種錯(cuò)誤的最終保障。然而,時(shí)不時(shí)地,我很想問:「誰自己測試這些測試?」來自 GeoServer 檢查的另一個(gè)警告再次證明了這一點(diǎn)。這是一個(gè)程式碼片段:

@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 在驗(yàn)證「e」引用是否為 null 之前,已使用該引用。 ResourceAccessManagerWCSTest.java 186、ResourceAccessManagerWCSTest.java 193

乍一看,這個(gè)警告似乎不是分析器最令人興奮的警告,因?yàn)?V6060 經(jīng)常是針對冗餘程式碼發(fā)出的。然而,我承諾我會根據(jù)他們的吸引力來選擇提名。所以,這個(gè)案例遠(yuǎn)比看起來有趣。

最初,測試邏輯可能看起來是錯(cuò)誤的,因?yàn)?e 變數(shù)是從 catch 運(yùn)算子取得的,並且進(jìn)一步保持不變,因此它永遠(yuǎn)不會為 null。我們可以進(jìn)行雜散編輯,並將 if(e == nul) 條件的 then 分支刪除為無法到達(dá)。然而,那是完全錯(cuò)誤的。你找到竅門了嗎?

關(guān)鍵在於包含異常物件的程式碼多了一個(gè)變量,它就是一個(gè)se。它的值會在循環(huán)體內(nèi)改變。所以,我們很容易猜測,條件中應(yīng)該要有se變量,而不是e。

這個(gè)錯(cuò)誤會導(dǎo)致then分支永遠(yuǎn)不會被執(zhí)行,所以我們不知道有沒有異常。更糟的是,在程式碼審查中很難注意到這樣的錯(cuò)誤,因?yàn)樽償?shù)名稱非常相似。

從這個(gè)故事可以汲取兩個(gè)智慧:

  1. 清楚地命名變量,即使在測試中也是如此。不然更容易犯這樣的錯(cuò)誤;
  2. 測試不足以保證專案質(zhì)量,因?yàn)樗鼈円部赡馨e(cuò)誤。因此,它會在應(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));
    ....
}

最後一次,試著自己找錯(cuò)誤-我會等...

Top most intriguing Java errors in 4

正在尋找?

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

當(dāng)然,有一個(gè)問題,但對於排名第一的問題來說還不夠有趣。是的,這裡有兩個(gè)錯(cuò)誤,我欺騙了你一點(diǎn)。但是沒有一點(diǎn)惡作劇的假期怎麼算呢? :)

分析器偵測到此處的 i^i 表達(dá)式有錯(cuò)誤,並發(fā)出以下警告:

V6001 在「^」運(yùn)算子的左邊和右邊有相同的子運(yùn)算式「i」。 LayoutFeeder.java 3897

異或運(yùn)算沒有任何意義,因?yàn)閮蓚€(gè)相同值的異或?qū)⒂肋h(yuǎn)為零。為了快速回顧一下,這裡是 XOR 的真值表:

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

換句話說,只有當(dāng)運(yùn)算元不同時(shí),運(yùn)算才會為真。我們將擁有相同的所有位,因?yàn)橹凳窍嗤摹?

為什麼我這麼喜歡這個(gè)bug?有 i^1 操作,看起來與 i^i 幾乎相同。因此,在程式碼審查中很容易錯(cuò)過這個(gè)錯(cuò)誤,因?yàn)槲覀円呀?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));
    ....
}

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

第二名。當(dāng)模式失敗時(shí)

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

PVS-Studio 分析器不喜歡從 TextWithOpen 類別的建構(gòu)函式呼叫 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)鍵的。至少,我以前是這麼認(rèn)為的。我專門寫了一篇文章來闡述我與這個(gè)錯(cuò)誤的鬥爭。

TextWithOpen 有許多子類,其中之一就是 TextWithOpenFile。在那裡,該方法實(shí)際上被重寫,它會傳回一個(gè)超類別沒有的字段,而不是 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è)類別的建構(gòu)子是什麼樣的?

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

注意到了嗎?呼叫超類別建構(gòu)函式後,將初始化二進(jìn)位欄位。然而,有一個(gè)對 isBinaryContents 方法的調(diào)用,它引用了子類別欄位!

Top most intriguing Java errors in 4

這是 PVS-Studio 警告:

V6052 在「TextWithOpen」父類別建構(gòu)子中呼叫重寫的「isBinaryContents」方法可能會導(dǎo)致使用未初始化的資料。檢查字段:二進(jìn)制。 TextWithOpenFile.java(77), TextWithOpen.java 59

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

第一名。一個(gè)錯(cuò)誤抵消了另一個(gè)錯(cuò)誤

高興吧!舞臺第一名!競爭很激烈,但必須做出選擇。經(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)這樣的錯(cuò)誤──當(dāng)然,除非你自己犯過這個(gè)錯(cuò)誤。我不會讓您久等的——這是 PVS-Studio 警告:

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

事實(shí)上,這個(gè)錯(cuò)誤非常簡單:StringBuilder 建構(gòu)子沒有接受 char 的重載。那麼呼叫什麼構(gòu)造函數(shù)呢?開發(fā)者顯然認(rèn)為會呼叫一個(gè)接受 String 的重載,然後 StringBuilder 的初始值就是這個(gè)斜線。

但是,會發(fā)生隱式型別轉(zhuǎn)換,並呼叫接受 int 的型別建構(gòu)函式。在我們的例子中,它代表 StringBuilder 的初始大小。將 char 作為參數(shù)傳遞不會在功能上影響任何內(nèi)容,因?yàn)樗粫谧罱K字串中。如果超出初始大小,它只會自行增加,不會導(dǎo)致異?;蚱渌弊饔?。

但是等等,我提到了兩個(gè)錯(cuò)誤,不是嗎?第二個(gè)在哪裡,它們是如何連結(jié)的?為了發(fā)現(xiàn)這一點(diǎn),我們必須讀入方法體並了解這段程式碼的作用。

它產(chǎn)生檔案或目錄的絕對路徑。根據(jù)程式碼,產(chǎn)生的路徑應(yīng)如下所示:

  • 對於檔案:/folder1/file
  • 對於目錄:/folder1/folder/.

程式碼看起來非常正確。這就是問題所在。程式碼確實(shí)可以正常工作:)但是如果我們透過用字串替換字元來修復(fù)錯(cuò)誤,我們將得到這個(gè)而不是正確的結(jié)果:

  • /資料夾1/檔案/;
  • /資料夾1/資料夾//

換句話說,我們會在字串末尾得到一個(gè)額外的斜杠。它將位於末尾,因?yàn)樯厦娴某淌酱a每次都會將新文字添加到行的開頭。

因此,第二個(gè)錯(cuò)誤是這個(gè)斜槓根本作為參數(shù)傳遞給建構(gòu)子。但是,我不會低估這樣的錯(cuò)誤,因?yàn)槿绻腥藳Q定在不檢查的情況下用字串替換字符,可能會出現(xiàn)問題。

這就是錯(cuò)誤頂部的第一個(gè)位置轉(zhuǎn)到正確工作的程式碼的方式。新年奇蹟,你期待什麼? :)

結(jié)論

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

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

所有這些錯(cuò)誤都是用PVS-Studio分析器偵測到的,最新版本(7.34)剛剛發(fā)布!您可以透過此連結(jié)嘗試。

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

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

新年快樂!

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

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

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的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允許一個(gè)null鍵和多個(gè)null值,Hashtable則不允許null鍵或值,否則拋出NullPointerException;3.性能方面,HashMap因無同步機(jī)制效率更高,Hashtable因每次操作加鎖性能較低,推薦使用ConcurrentHashMap替

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

Java使用包裝類是因?yàn)榛緮?shù)據(jù)類型無法直接參與面向?qū)ο癫僮?,而?shí)際需求中常需對象形式;1.集合類只能存儲對象,如List利用自動(dòng)裝箱存儲數(shù)值;2.泛型不支持基本類型,必須使用包裝類作為類型參數(shù);3.包裝類可表示null值,用於區(qū)分未設(shè)置或缺失的數(shù)據(jù);4.包裝類提供字符串轉(zhuǎn)換等實(shí)用方法,便於數(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)、熱點(diǎn)檢測與編譯、類型推測與去虛擬化、冗餘操作消除四種方式優(yōu)化代碼。 1.方法內(nèi)聯(lián)減少調(diào)用開銷,將頻繁調(diào)用的小方法直接插入調(diào)用處;2.熱點(diǎn)檢測識別高頻執(zhí)行代碼並集中優(yōu)化,節(jié)省資源;3.類型推測收集運(yùn)行時(shí)類型信息實(shí)現(xiàn)去虛擬化調(diào)用,提升效率;4.冗餘操作消除根據(jù)運(yùn)行數(shù)據(jù)刪除無用計(jì)算和檢查,增強(qiáng)性能。

什麼是實(shí)例初始器塊? 什麼是實(shí)例初始器塊? Jun 25, 2025 pm 12:21 PM

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

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

工廠模式用於封裝對象創(chuàng)建邏輯,使代碼更靈活、易維護(hù)、松耦合。其核心答案是:通過集中管理對象創(chuàng)建邏輯,隱藏實(shí)現(xiàn)細(xì)節(jié),支持多種相關(guān)對象的創(chuàng)建。具體描述如下:工廠模式將對象創(chuàng)建交給專門的工廠類或方法處理,避免直接使用newClass();適用於多類型相關(guān)對象創(chuàng)建、創(chuàng)建邏輯可能變化、需隱藏實(shí)現(xiàn)細(xì)節(jié)的場景;例如支付處理器中通過工廠統(tǒng)一創(chuàng)建Stripe、PayPal等實(shí)例;其實(shí)現(xiàn)包括工廠類根據(jù)輸入?yún)?shù)決定返回的對象,所有對象實(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)換自動(dòng)發(fā)生,如將int轉(zhuǎn)為double;2.顯式轉(zhuǎn)換需手動(dòng)操作,如使用(int)myDouble。需要類型轉(zhuǎn)換的情況包括處理用戶輸入、數(shù)學(xué)運(yùn)算或函數(shù)間傳遞不同類型的值時(shí)。需要注意的問題有:浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)會截?cái)嘈?shù)部分、大類型轉(zhuǎn)小類型可能導(dǎo)致數(shù)據(jù)丟失、某些語言不允許直接轉(zhuǎn)換特定類型。正確理解語言的轉(zhuǎn)換規(guī)則有助於避免錯(cuò)誤。

See all articles