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

Heim Java javaLernprogramm Die faszinierendsten Java-Fehler in 4

Die faszinierendsten Java-Fehler in 4

Jan 01, 2025 am 09:19 AM

Im Jahr 2024 haben wir eine Fülle von Projekten analysiert und unsere Erkenntnisse auf unserem Blog geteilt. Jetzt ist Silvester – es ist Zeit, festliche Geschichten zu erz?hlen! Wir haben die faszinierendsten Java-Fehler gesammelt, die in Open-Source-Projekten entdeckt wurden, und stellen sie Ihnen jetzt vor!

Top most intriguing Java errors in 4

Vorwort

Wir pflegen seit langem die Tradition, die interessantesten mit PVS-Studio entdeckten Fehler zu ver?ffentlichen, aber seit 2020 gab es keinen Java-bezogenen Top! Dieses Mal habe ich versucht, die Vintage-Rubrik wiederzubeleben. Ich hoffe, Sie haben eine kuschelige Decke und eine warme Tasse Tee zur Hand, denn ich habe über 10 unterhaltsame K?fer speziell für Sie ausgew?hlt. So wurden sie eingestuft:

  • meine pers?nliche Meinung;
  • ein interessanter Hintergrund des Fehlers;
  • Vielfalt, Glaubwürdigkeit und Nicht-Trivialit?t.

Machen Sie sich bereit für 10 unterhaltsame Geschichten mit ihren eigenen Programmierweisheiten – schlie?lich steht Silvester bald vor der Tür :)

10. Platz. Zurück in die Zukunft

An zehnter Stelle empf?ngt uns der erste Codeausschnitt mit offenen Armen.

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

Ich konnte nicht anders, als es in das Silvester-Top aufzunehmen, weil ein Fehler in diesem Code es uns erm?glicht, schneller zum n?chsten Jahr zu reisen :) Ratet mal, woher der Fehler kommt?

Sehen wir uns das Argument an, das an den SimpleDateFormat-Konstruktor übergeben wird. Scheint es gültig zu sein? Wenn wir dort fast ein beliebiges Datum übergeben, beispielsweise das Datum, an dem dieser Artikel geschrieben wurde (12.10.2024), gibt der Code den korrekten Wert zurück: 20241210.

Wenn wir jedoch den 29.12.2024 überschreiten, wird stattdessen 20251229 zurückgegeben und so auf geniale Weise früher ins neue Jahr verschoben. Eine Zeitreise zurück in die Vergangenheit ist übrigens auch machbar.

Dies geschieht, weil das Y-Zeichen im Argument von SimpleDateFormat das Jahr basierend auf der Wochennummer darstellt. Kurz gesagt gilt eine Woche als erste Woche, wenn sie mindestens vier Tage des neuen Jahres umfasst. Wenn unsere Woche also am Sonntag beginnt, k?nnen wir drei Tage früher ins neue Jahr starten.

Um das Problem zu beheben, ersetzen Sie einfach ein gro?es Y durch ein kleines y. M?chten Sie mehr erfahren? Wir haben diesem Thema einen ganzen Beitrag gewidmet.

Hier ist eine PVS-Studio-Warnung für diesen Fehler:

V6122 Verwendung des Musters ?Y“ (Woche, Jahr) wurde erkannt: Es war wahrscheinlich beabsichtigt, ?y“ (Jahr) zu verwenden. SkeinParameters.java 246

Aufgrund der Besonderheiten der Wochennummer sind Tests nicht der beste Weg, um diesen Fehler zu finden. Warum kommt so ein aktueller Fehler überhaupt erst an letzter Stelle? Der Grund dafür ist, dass die Warnung nicht von der tats?chlichen Version von Bouncy Castle stammt, sondern von unserer Testbasis. Die alten Quellen sind immer noch vorhanden und dieser Fehler wurde schon vor langer Zeit behoben. Das ist so ein Gru? an die Vergangenheit, einfach mal wieder eine Zeitreise :)

9. Platz. ?Scheint nicht zu funktionieren“

An neunter Stelle haben wir die Warnung aus der GeoServer-Analyse:

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

Hier ist die PVS-Studio-Warnung:

V6027 Die Variablen ?newValue“, ?oldValue“ werden durch den Aufruf derselben Funktion initialisiert. Es handelt sich wahrscheinlich um einen Fehler oder um nicht optimierten Code. DataAccessRuleDAOTest.java 110, DataAccessRuleDAOTest.java 111

Was ist an einem solchen Fehler interessant? Lassen Sie mich verraten, was sich hinter den vier Punkten verbirgt:

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

Es gibt einen Kommentar, dass der Code aus irgendeinem Grund nicht funktioniert. Ehrlich gesagt, ich musste schmunzeln, als ich es zum ersten Mal sah.

Der Kommentar ist allerdings eher zweideutig. Es ist wahrscheinlich, dass der Test absichtlich so geschrieben wurde, um einen Fehler zu verhindern, w?hrend der Vergleich nicht funktioniert. Der Code befindet sich jedoch seit über einem Jahrzehnt in diesem Zustand, was einige Fragen aufwirft. Diese Mehrdeutigkeit ist der Grund, warum ich es nicht h?her einstufe.

8. Platz. Schuss in den Fu?

Wenn wir Bugs von JBullet nicht als Schusswaffen bezeichnen k?nnen, wei? ich nicht, welche wir so nennen k?nnen. Hier ist ein Fehler aus dem Artikel:

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

Ich denke, wir brauchen nicht einmal die PVS-Studio-Warnung, um zu erkennen, wo der Fehler liegt. Wie auch immer, nur für den Fall, hier ist es:

V6026 Dieser Wert ist bereits der Variablen ?proxy1“ zugewiesen. HashedOverlappingPairCache.java 233

Ja, es ist ein peinlich einfacher Fehler. Diese Einfachheit macht es jedoch noch urkomischer. Dennoch hat es seine eigene Geschichte.

Die JBullet-Bibliothek ist eine Portierung der C/C-Bullet-Bibliothek, und dort gibt es eine ?hnliche Funktion:

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

Es ist leicht zu erkennen, dass dieser Code korrekt geschrieben ist. Der Git-Schuld nach zu urteilen, ist es ursprünglich korrekt geschrieben. Es stellte sich heraus, dass der Fehler auftrat, als der Code von einer Sprache in eine andere portiert wurde.

Für seine auff?llige Schlichtheit gepaart mit einer reichen Geschichte vergebe ich dieser Warnung den achten Platz. Ich hoffe, es hat Ihnen gefallen, dass sich herausstellte, dass der Schuss-in-den-Fu?-Bug mit C zusammenh?ngt.

7. Platz. Selbst gro?e Mathematiker machen Fehler

Zugegebenerma?en w?rmt mir die n?chste Warnung aus vielen Gründen das Herz. Hier ist ein Codeausschnitt aus dem GeoGebra-Check:

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

Versuchen Sie, den Fehler selbst zu finden! Um Sie davon abzuhalten, einen Blick darauf zu werfen, habe ich die Warnung und Erkl?rung in einem Spoiler versteckt.

Die Antwort
Schauen wir uns zun?chst die PVS-Studio-Warnung an:

V6107 Die Konstante 0,7071067811865 wird verwendet. Der resultierende Wert k?nnte ungenau sein. Erw?gen Sie die Verwendung von Math.sqrt(0.5). DrawAngle.java 303

In Wirklichkeit ist 0,7071067811865 keine magische Zahl – es ist einfach das gerundete Ergebnis der Quadratwurzelbildung aus 0,5. Doch wie kritisch ist dieser Pr?zisionsverlust? GeoGebra ist eine auf Mathematiker zugeschnittene Software, und zus?tzliche Pr?zision scheint dort nicht zu schaden.

Warum gef?llt mir dieser K?fer so gut?

Erstens bitte ich die Teilnehmer auf Konferenzen oft, einen ?hnlichen Fehler in anderen Codefragmenten zu finden. Es war immer unterhaltsam, ihnen dabei zuzusehen, wie sie den Code sorgf?ltig analysieren, wenn der Fehler in einer Konstante verborgen ist.

Zweitens ist dies meine erste Diagnoseregel, die für den Java-Analysator implementiert wurde. Deshalb konnte ich es mir nicht verkneifen, es ganz oben zu platzieren – trotz allem Bewusstsein der Voreingenommenheit – ich habe es auf den siebten Platz gesetzt :)

6. Platz. Dieses Muster funktioniert nicht

Die folgende Warnung, die ich dem ersten Artikel basierend auf dem DBeaver-Check entnommen habe, erregt m?glicherweise nicht sofort unsere Aufmerksamkeit. Hier ist ein Codefragment:

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

Das hat der PVS-Studio-Analysator erkannt:

V6082 Unsichere, doppelt überprüfte Verriegelung. Das Feld sollte als flüchtig deklariert werden. TaskImpl.java 59, TaskImpl.java317

Obwohl diese spezielle Warnung nichts Besonderes ist, finde ich sie dennoch sehr faszinierend. Der Punkt ist, dass das angewendete Double-Checked Locking-Muster nicht funktioniert. Was ist der Trick? Das war vor 20 Jahren relevant :)

Wenn Sie mehr über das Thema lesen m?chten, empfehle ich Ihnen, den vollst?ndigen Artikel zu lesen. Aber lassen Sie mich zun?chst eine kurze Zusammenfassung geben.

Das Double-Checked Locking-Muster wird verwendet, um eine verz?gerte Initialisierung in Multithread-Umgebungen zu implementieren. Vor der ?Heavyweight“-Prüfung wird die ?Lightweight“-Prüfung ohne Synchronisationsblock ausgeführt. Die Ressource wird nur erstellt, wenn beide Prüfungen erfolgreich sind.

Bei diesem Ansatz ist die Objekterstellung jedoch nicht atomar und der Prozessor und Compiler k?nnen die Operationsreihenfolge ?ndern. Daher kann es passieren, dass ein anderer Thread versehentlich ein teilweise erstelltes Objekt empf?ngt und damit beginnt, damit zu arbeiten, was zu fehlerhaftem Verhalten führen kann. Dieser Fehler kann selten auftreten, daher wird das Debuggen eine gro?e Herausforderung für Entwickler sein.

Hier ist eine Wendung: Dieses Muster funktionierte erst mit JDK 5. Ab JDK 5 wurde das Schlüsselwort volatile eingeführt, um das potenzielle Problem der Neuordnung von Vorg?ngen dank des passiert-bevor-Prinzips zu l?sen. Der Analysator warnt uns, dass wir dieses Schlüsselwort hinzufügen sollten.

Es w?re jedoch besser, dieses Muster trotzdem zu vermeiden. Die Hardware- und JVM-Leistung hat sich seitdem erheblich verbessert und die synchronisierten Vorg?nge sind nicht mehr so ??langsam. Allerdings bleibt die falsche Implementierung des DCL-Musters eine h?ufige Gefahr mit den oben beschriebenen potenziell schwerwiegenden Folgen. Es best?tigt die Tatsache, dass unser Analysator immer noch solche fahrl?ssigen Fehler in alten Projekten findet.

5. Platz. Mikrooptimierung

Der fünfte Platz belegt eine weitere DBeaver-Warnung, der wir einen Artikel gewidmet haben. Werfen wir einen Blick darauf:

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

Hier ist eine Erkl?rung:

V6030 Die Methode rechts vom Operator ?&“ wird unabh?ngig vom Wert des linken Operanden aufgerufen. Vielleicht ist es besser, ?&&“ zu verwenden. ExasolTableColumnManager.java 79, DB2TableColumnManager.java 77

Der Entwickler hat das logische && mit dem bitweisen & verwechselt. Sie haben ein unterschiedliches Verhalten: Die Bedingungen im Ausdruck werden nach dem bitweisen UND nicht beendet. Die Kurzschlussauswertung funktioniert nicht für bitweises UND. Auch wenn exasolTableBase != null false zurückgibt, erreicht der Ausführungsthread exasolTableBase.getClass() und führt zu einem NPE.

Okay, es ist nur ein Tippfehler, lass uns weitermachen, ja? DBeaver hat viele solcher Warnungen. Eine Menge. Viele sind relativ harmlos, aber für neugierige Leser habe ich unten ein paar Beispiele hinterlassen:

Verwendung bitweiser Operationen, die nicht zu Fehlern führen
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);
  }
}

Nachdem ich tiefer gegraben habe, ist mein Team davon ausgegangen, dass die Entwickler m?glicherweise versucht haben, die Leistung mikrozu optimieren. Für ein vollst?ndiges Bild k?nnen Sie sich unseren Artikel ansehen – hier stelle ich eine Zusammenfassung vor.

Der entscheidende Punkt ist, dass bitweise Operationen nicht auf Verzweigungsvorhersagen basieren, was m?glicherweise eine schnellere Ausführung im Vergleich zu logischen Operationen erm?glicht.

Zu unserer überraschung unterstützt ein selbst entwickelter Benchmark diese Behauptung:

Top most intriguing Java errors in 4

Das Diagramm zeigt die ben?tigte Zeit für jeden Vorgangstyp. Wenn wir ihm vertrauen, scheinen die bitweisen Operationen 40 % schneller zu sein als logische Operationen.

Warum spreche ich dieses Thema an? Um die Kosten potenzieller Mikrooptimierungen hervorzuheben.

Erstens haben Entwickler die Verzweigungsvorhersage aus einem bestimmten Grund erfunden – es w?re zu teuer, sie aufzugeben. Daher arbeitet der Benchmark wahrscheinlich schneller, da die Werte eine Normalverteilung aufweisen, die in realen F?llen wahrscheinlich nicht zu beobachten ist.

Zweitens kann der Verzicht auf den Kurzschlussbewertungsmechanismus zu deutlich h?heren Kosten führen. Wenn wir uns das dritte Beispiel aus dem Spoiler oben ansehen, k?nnen wir sehen, dass nicht der schnellste Vorgang immer ausgeführt wird, anstatt sofort anzuhalten.

Drittens gew?hren wir von Beginn des Kapitels an einen Freibrief für solche Fehler.

Insgesamt finde ich die warnende Geschichte des Mikrooptimierungspreises überzeugend genug, um unsere Top 5 zu er?ffnen.

4. Platz. Der Test wird nicht scheitern, wenn er nicht funktioniert

Automatisierte Tests gelten oft als ultimativer Schutz vor verschiedenen Fehlern. Hin und wieder bin ich jedoch versucht zu fragen: ?Wer führt die Tests selbst durch?“ Eine weitere Warnung des GeoServer-Checks verdeutlicht dies noch einmal. Hier ist ein Codefragment:

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

Die PVS-Studio-Warnung:

V6060 Die ?e“-Referenz wurde verwendet, bevor sie mit Null verglichen wurde. ResourceAccessManagerWCSTest.java 186, ResourceAccessManagerWCSTest.java 193

Auf den ersten Blick scheint diese Warnung nicht die aufregendste Warnung des Analysators zu sein, da V6060 h?ufig für redundanten Code ausgegeben wird. Dennoch habe ich versprochen, dass ich die Nominierungen nach ihrer Attraktivit?t ausw?hlen werde. Dieser Fall ist also weitaus interessanter, als er scheint.

Anfangs mag die Testlogik falsch erscheinen, da die e-Variable vom Catch-Operator erhalten wird und weiterhin unver?ndert bleibt, sodass sie niemals null sein wird. Wir k?nnen einfach eine verirrte Bearbeitung vornehmen und den then-Zweig der if(e == nul)-Bedingung als nicht erreichbar entfernen. Doch das w?re radikal falsch. Hast du den Haken schon herausgefunden?

Der Schlüssel liegt in einer weiteren Variablen im Code, die das Ausnahmeobjekt enth?lt, es ist ein se. Es hat einen Wert, der sich innerhalb des Schleifenk?rpers ?ndert. Wir k?nnen also leicht erraten, dass in der Bedingung die se-Variable anstelle von e vorhanden sein sollte.

Dieser Fehler führt dazu, dass der then-Zweig nie ausgeführt wird, sodass wir nicht wissen, dass es keine Ausnahme gibt. Was noch schlimmer ist, es ist ziemlich schwierig, einen solchen Fehler bei einer Codeüberprüfung zu bemerken, weil die Variablennamen sehr ?hnlich sind.

Aus dieser Geschichte lassen sich zwei Weisheiten ableiten:

  1. Benennen Sie Variablen klar, auch in Tests. Andernfalls ist es einfacher, solche Fehler zu machen;
  2. Tests reichen nicht aus, um die Projektqualit?t zu gew?hrleisten, da sie auch Fehler enthalten k?nnen. Dadurch entstehen Lücken für Fehler in der App.

Für die Vermittlung solch wertvoller Lektionen vergebe ich dieser Warnung den vierten Platz.

3. Platz. Viel Spa? beim Debuggen, Leute

Die ersten drei Gewinner geh?ren zur Warnung aus dem NetBeans-Check. Frühere Codeausschnitte waren relativ kompakt, schauen wir uns also einen l?ngeren an:

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

Versuchen Sie zum letzten Mal, den Fehler selbst zu finden – ich werde warten...

Top most intriguing Java errors in 4

Suchen?

Sch?n! Diejenigen, die den Fehler nur im Ausdruck iDesc.neighbor != null || gefunden haben iDesc.index == iDesc.index, es tut mir leid, das sagen zu müssen – du hast verloren :)

Sicher, es gibt ein Problem, aber es ist bei weitem nicht interessant genug für das oberste. Ja, hier liegen zwei Fehler vor, ich habe dich ein wenig get?uscht. Aber was w?ren Feiertage ohne ein bisschen Unfug? :)

Der Analysator hat hier einen Fehler im i^i-Ausdruck erkannt und die folgende Warnung ausgegeben:

V6001 Links und rechts vom Operator ?^“ gibt es identische Unterausdrücke ?i“. LayoutFeeder.java 3897

Die XOR-Operation macht keinen Sinn, da das Exklusiv-ODER mit zwei identischen Werten immer Null ist. Zur schnellen Auffrischung finden Sie hier die Wahrheitstabelle für XOR:

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

Mit anderen Worten, die Operation ist nur dann wahr, wenn die Operanden unterschiedlich sind. Wir werden alle Bits gleich haben, da der Wert derselbe ist.

Warum hat mir dieser K?fer so gut gefallen? Es gibt die i^1-Operation, die fast identisch mit i^i aussieht. Daher ist es unglaublich leicht, diesen Fehler bei einer Codeüberprüfung zu übersehen, da wir oben bereits das richtige i^1 gesehen haben.

Ich wei? nicht, wie es dir geht, aber es erinnert mich an das berühmte:

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

Ansonsten ist es schwer zu erkl?ren, wie es in den Code gelangt ist – es sei denn, wir verwerfen die langweilige Version mit einem einfachen Tippfehler. Wenn Sie diesen Fehler entdeckt haben, klopfen Sie sich selbst auf die Schulter – oder teilen Sie Ihre detektivischen F?higkeiten in den Kommentaren :)

2. Platz. Als Muster versagten

Ich habe die Fehler aus dem ersten und dritten DBeaver-Artikel bereits gezeigt und den zweiten übersprungen. Ich stehe korrigiert da – das Folgende stammt nur aus dem zweiten Artikel.

PVS-Studio-Analysator mag es nicht, dass isBinaryContents vom Konstruktor der TextWithOpen-Klasse aufgerufen wird, der in den Unterklassen überschrieben wird:

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

Na und? Es wird überschrieben – aber keine gro?e Sache. Es scheint ein Codegeruch zu sein, nichts Kritisches. Zumindest habe ich das früher gedacht. Ich habe meinem Kampf mit diesem Fehler einen Artikel gewidmet.

TextWithOpen hat viele Unterklassen und eine davon ist TextWithOpenFile. Dort wird die Methode tats?chlich überschrieben und statt false gibt sie ein Feld zurück, das die Superklasse nicht hat:

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

Schon misstrauisch? Wie sieht der Konstruktor dieser Klasse aus?

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

Merken Sie das? Das Bin?rfeld wird initialisiert, nachdem der Superklassenkonstruktor aufgerufen wurde. Es gibt jedoch einen Aufruf der Methode isBinaryContents, die auf das Unterklassenfeld verweist!

Top most intriguing Java errors in 4

Hier ist die PVS-Studio-Warnung:

V6052 Der Aufruf der überschriebenen Methode ?isBinaryContents“ im Konstruktor der übergeordneten Klasse ?TextWithOpen“ kann zur Verwendung nicht initialisierter Daten führen. Feld prüfen: bin?r. TextWithOpenFile.java(77), TextWithOpen.java 59

Es ist ein ziemlich unterhaltsames Bild. Auf den ersten Blick schien der Entwickler die Best Practices zu befolgen: Vermeiden Sie den Code-Spaghetti, der unm?glich zu warten ist, und versuchen Sie, kanonisches OOP durch ein Vorlagenmethodenmuster zu implementieren. Aber selbst bei der Implementierung eines so einfachen Musters k?nnen wir einen Fehler machen, und genau das ist passiert. Meiner Meinung nach ist solch eine (trügerische) Sch?nheit in der Einfachheit ein solider zweiter Platz.

1. Platz. Ein Fehler glich den anderen aus

Freut euch! Der erste Platz auf der Bühne! Der Wettbewerb war hart, aber die Wahl musste getroffen werden. Nach langem überlegen habe ich mich entschieden, die Warnung aus dem NetBeans-Check zu übernehmen. Lassen Sie mich den letzten Codeausschnitt vorstellen:

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

Ich bin zuversichtlich, dass es unm?glich ist, einen solchen Fehler auf den ersten Blick zu erkennen – es sei denn natürlich, Sie haben diesen Fehler selbst gemacht. Ich werde Sie nicht warten lassen – hier ist die PVS-Studio-Warnung:

V6009 Die Pufferkapazit?t wird mithilfe eines char-Werts auf ?47“ festgelegt. H?chstwahrscheinlich sollte das Symbol ?/“ im Puffer platziert werden. IgnoreUnignoreCommand.java 107

Tats?chlich ist der Fehler l?cherlich elementar: Der StringBuilder-Konstruktor hat keine überladung, die Zeichen akzeptiert. Welcher Konstruktor hei?t dann? Der Entwickler dachte offenbar, dass ein überlastungsf?higer String aufgerufen würde und der Anfangswert von StringBuilder dann dieser Schr?gstrich w?re.

Es findet jedoch eine implizite Typkonvertierung statt und der Typkonstruktor, der int akzeptiert, wird aufgerufen. In unserem Fall stellt es die Anfangsgr??e von StringBuilder dar. Die übergabe von char als Argument hat keine funktionalen Auswirkungen, da es nicht in die endgültige Zeichenfolge einbezogen wird. Wenn die ursprüngliche Gr??e überschritten wird, vergr??ert sie sich einfach von selbst, ohne Ausnahmen oder andere Nebenwirkungen zu verursachen.

Aber Moment, ich habe zwei Fehler erw?hnt, nicht wahr? Wo ist die zweite und wie h?ngen sie zusammen? Um dies zu erkennen, müssen wir den Methodenk?rper lesen und erkennen, was dieser Code bewirkt.

Es generiert einen absoluten Pfad zu einer Datei oder einem Verzeichnis. Basierend auf dem Code sollte der resultierende Pfad etwa so aussehen:

  • für eine Datei: /folder1/file
  • für ein Verzeichnis: /folder1/folder/.

Der Code sieht ganz korrekt aus. Das ist das Problem. Der Code funktioniert wirklich so, wie er sollte :) Aber wenn wir den Fehler beheben, indem wir ein Zeichen durch eine Zeichenfolge ersetzen, erhalten wir Folgendes anstelle des richtigen Ergebnisses:

  • /folder1/file/;
  • /folder1/folder//

Mit anderen Worten, wir erhalten einen zus?tzlichen Schr?gstrich am Ende der Zeichenfolge. Es befindet sich am Ende, da der obige Code jedes Mal neuen Text am Anfang der Zeile hinzufügt.

Daher besteht der zweite Fehler darin, dass dieser Schr?gstrich überhaupt als Argument an den Konstruktor übergeben wurde. Allerdings würde ich einen solchen Fehler nicht untersch?tzen, denn wenn jemand beschlie?t, ein Zeichen ohne Prüfung durch eine Zeichenfolge zu ersetzen, kann es zu Problemen kommen.

So belegt Code, der korrekt funktioniert, den ersten Platz in der Fehlerliste. Neujahrswunder, was haben Sie erwartet? :)

Abschluss

Ich hoffe, es hat Ihnen Spa? gemacht, meine Fehlergeschichten zu lesen. Wenn Ihnen eine bestimmte Geschichte aufgefallen ist – oder wenn Sie Vorschl?ge zur Anpassung des Rankings haben – teilen Sie uns Ihre Gedanken gerne in den Kommentaren mit. Ich werde sie für das n?chste Mal im Hinterkopf behalten :)

Wenn Sie sich für andere Sprachen interessieren, lade ich Sie ein, sich hier die gr??ten C#-Fehler für 2024 anzusehen – bleiben Sie gespannt auf neue Spitzen!

Alle diese Fehler wurden mit dem PVS-Studio-Analysetool erkannt und die neueste Version (7.34) wurde gerade ver?ffentlicht! Sie k?nnen es über diesen Link ausprobieren.

Um über neue Artikel zur Codequalit?t auf dem Laufenden zu bleiben, laden wir Sie ein, sich anzumelden:

  • PVS-Studio X (Twitter);
  • unser monatlicher Artikelüberblick;

Frohes Neues Jahr!

Das obige ist der detaillierte Inhalt vonDie faszinierendsten Java-Fehler in 4. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erkl?rung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Hei?e KI -Werkzeuge

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem v?llig kostenlosen KI-Gesichtstausch-Tool aus!

Hei?e Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Unterschied zwischen Hashmap und Hashtable? Unterschied zwischen Hashmap und Hashtable? Jun 24, 2025 pm 09:41 PM

Der Unterschied zwischen HashMap und Hashtable spiegelt sich haupts?chlich in der Gewindesicherheit, der Nullwertunterstützung und der Leistung wider. 1. In Bezug auf die Gewindesicherheit ist Hashtable Thread-Safe, und seine Methoden sind haupts?chlich Synchronmethoden, w?hrend HashMap keine Synchronisationsverarbeitung durchführt, die nicht mit Thread-Safe ist. 2. In Bezug auf die Nullwertunterstützung erm?glicht HashMap einen Nullschlüssel und mehrere Nullwerte, w?hrend Hashtable keine Nullschlüssel oder -Werte zul?sst, sonst wird eine Nullpointerexception geworfen. 3. In Bezug auf die Leistung ist HashMap effizienter, da kein Synchronisationsmechanismus vorhanden ist und Hashtable für jeden Vorgang eine niedrige Verriegelungsleistung aufweist. Es wird empfohlen, stattdessen eine Concurrenthashmap zu verwenden.

Warum brauchen wir Wrapper -Klassen? Warum brauchen wir Wrapper -Klassen? Jun 28, 2025 am 01:01 AM

Java verwendet Wrapper-Klassen, da grundlegende Datentypen nicht direkt an objektorientierten Operationen teilnehmen k?nnen und Objektformen h?ufig in den tats?chlichen Bedürfnissen erforderlich sind. 1. Sammelklassen k?nnen nur Objekte speichern, z. B. Listen verwenden automatische Boxen, um numerische Werte zu speichern. 2. Generika unterstützen keine Grundtypen, und Verpackungsklassen müssen als Typparameter verwendet werden. 3.. Verpackungsklassen k?nnen Nullwerte darstellen, um nicht festgelegte oder fehlende Daten zu unterscheiden. 4. Verpackungsklassen bieten praktische Methoden wie String -Conversion, um die Analyse und Verarbeitung von Daten zu erleichtern. In Szenarien, in denen diese Eigenschaften ben?tigt werden, sind Verpackungsklassen unverzichtbar.

Was sind statische Methoden in Schnittstellen? Was sind statische Methoden in Schnittstellen? Jun 24, 2025 pm 10:57 PM

StaticMethodsinInterfaces -reisEtroducucuedInjava8toalloytilityFunctionSwitHinTheInterfaceItEp.beejava8, solche Funktionen, dieseparatehelperklassen, führendemTodisorganizedCode.Now, StaticMetheSprovidreefits: 1) theeneNableable -theenableaby

Wie optimiert JIT Compiler den Code? Wie optimiert JIT Compiler den Code? Jun 24, 2025 pm 10:45 PM

Der JIT -Compiler optimiert den Code durch vier Methoden: Methode Inline, Hotspot -Erkennung und -vergleich, Typespekulation und Devirtualisation sowie die Eliminierung des redundanten Betriebs. 1. Methode Inline reduziert den Anrufaufwand und fügt h?ufig kleine Methoden direkt in den Anruf ein. 2. Erkennung und Hochfrequenzcodeausführung und zentral optimieren, um Ressourcen zu sparen. 3. Typ Spekulation sammelt Informationen zum Laufzeittyp, um Devirtualisation -Anrufe zu erzielen und die Effizienz zu verbessern. 4. Redundante Operationen beseitigen nutzlose Berechnungen und Inspektionen basierend auf den Betriebsdaten, wodurch die Leistung verbessert wird.

Was ist ein Instanz -Initialisiererblock? Was ist ein Instanz -Initialisiererblock? Jun 25, 2025 pm 12:21 PM

Instanzinitialisierungsbl?cke werden in Java verwendet, um die Initialisierungslogik beim Erstellen von Objekten auszuführen, die vor dem Konstruktor ausgeführt werden. Es ist für Szenarien geeignet, in denen mehrere Konstruktoren Initialisierungscode, komplexe Feldinitialisierung oder anonyme Szenarien der Klasseninitialisierung teilen. Im Gegensatz zu statischen Initialisierungsbl?cken wird es jedes Mal ausgeführt, wenn es instanziiert wird, w?hrend statische Initialisierungsbl?cke nur einmal ausgeführt werden, wenn die Klasse geladen wird.

Was ist das Fabrikmuster? Was ist das Fabrikmuster? Jun 24, 2025 pm 11:29 PM

Der Werksmodus wird verwendet, um die Logik der Objekterstellung zusammenzufassen, wodurch der Code flexibler, einfach zu pflegen und locker gekoppelt ist. Die Kernantwort lautet: Durch zentrales Verwalten von Logik der Objekterstellung, das Ausblenden von Implementierungsdetails und die Unterstützung der Erstellung mehrerer verwandter Objekte. Die spezifische Beschreibung lautet wie folgt: Der Fabrikmodus gibt Objekterstellung an eine spezielle Fabrikklasse oder -methode zur Verarbeitung und vermeidet die Verwendung von NewClass () direkt; Es ist für Szenarien geeignet, in denen mehrere Arten von verwandten Objekten erstellt werden, die Erstellungslogik sich ?ndern und Implementierungsdetails versteckt werden müssen. Zum Beispiel werden im Zahlungsabwickler Stripe, PayPal und andere Instanzen durch Fabriken erstellt. Die Implementierung umfasst das von der Fabrikklasse zurückgegebene Objekt basierend auf Eingabeparametern, und alle Objekte erkennen eine gemeinsame Schnittstelle. Gemeinsame Varianten umfassen einfache Fabriken, Fabrikmethoden und abstrakte Fabriken, die für unterschiedliche Komplexit?ten geeignet sind.

Was ist das 'Final' -Styword für Variablen? Was ist das 'Final' -Styword für Variablen? Jun 24, 2025 pm 07:29 PM

InvaVa, theFinalKeywordPreventsAvariable von ValueFromBeingumedAfterasssignment, ButitsBehaviordiffersForprimitive und ANSPRIMITIVEVARIABLE, FinalMakesthevalueconstant, AsinfinalIntmax_speed = 100; WhirerastsignmentcausaSesSaSesSaSesSaSaSesSaSesSaSaSesSaSaSesSaSesSesirror

Was ist Typ Casting? Was ist Typ Casting? Jun 24, 2025 pm 11:09 PM

Es gibt zwei Arten von Konvertierung: implizit und explizit. 1. Die implizite Umwandlung erfolgt automatisch, wie z. B. das Konvertieren in INT in Doppel; 2. Explizite Konvertierung erfordert einen manuellen Betrieb, z. B. die Verwendung (int) MyDouble. Ein Fall, in dem die Typ -Konvertierung erforderlich ist, umfasst die Verarbeitung von Benutzereingaben, mathematische Operationen oder das übergeben verschiedener Werte zwischen Funktionen. Probleme, die beachtet werden müssen, sind: Umdrehung von Gleitpunktzahlen in Ganzzahlen wird der fraktionale Teil abschneiden, gro?e Typen in kleine Typen zu einem Datenverlust führen, und einige Sprachen erm?glichen keine direkte Konvertierung bestimmter Typen. Ein ordnungsgem??es Verst?ndnis der Regeln der Sprachkonvertierung hilft, Fehler zu vermeiden.

See all articles