Frage

ich eine Methode hat eine bestimmte Anzahl von Tagen auf Millisekunden zu konvertieren:

private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = expireTimeInDays * 24 * 60 * 60 * 1000;
}

Ich hatte eine harte Zeit, um herauszufinden, was ich falsch gemacht habe. Nun meine Frage: Ist dieser Fehler so offensichtlich?

Die korrigierte Methode:

private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = ((long) expireTimeInDays) * 24 * 60 * 60 * 1000;
}

Wenn ich vor der Berechnung nicht die ganze Zahl zu lange konvertieren, erhalte ich ein komplettes falsches Ergebnis.

War es hilfreich?

Lösung

Ist es offensichtlich? Ich denke, es hängt davon ab, wie lange Sie haben Java benutze und wie oft haben Sie mit Millisekunden zu tun haben. Natürlich sollte es bis zu etwa 24 Tage in Ordnung sein ...

Ich denke, der größte Hinweis, dass System.currentTimeMillis() eine long zurück sein sollte. Das ist ein gutes Indiz dafür, dass eine Anzahl von Millisekunden kann groß werden. Der Typ der Variablen sind Einstellung, die Sie sollten auch einen guten Hinweis darauf sein.

Natürlich, Sie haben auch bekam wissen, dass, wenn Sie mit ints arithmetischen Operationen zu tun, wird das Ergebnis mit Umgriff bei Überlauf int werden. Ob die ausreichend klar oder nicht könnte diskutiert, aber es wäre eine ziemlich sinnlos Diskussion. In C #, wenn Sie Überlauf eingeschaltet Überprüfung, würde haben Sie den Fehler recht schnell gefunden -. Aber dann nicht viele Entwickler tun, dass (in der Tat, ich weiß nicht, obwohl ich wahrscheinlich sollte)

Andere Tipps

Ja, es ist ziemlich offensichtlich, wenn Sie es vorher getan haben. Jedes Mal, wenn eine Reihe von Zahlen sehen ausmultipliziert Sie automatisch sollte denken über Integer-Überlauf-Fehler starten. In diesem Fall sind Sie auf überlaufen, wenn expireTimeInDays mehr als 24 Technisch gesehen ist, sollten Sie über Überlauffehler denken Sie jederzeit mit ganzen Zahlen arbeiten , sondern eine Gruppe von ihnen Multiplikation wie dies sollte eine sehr große rote Fahne.

Ihre Operanden Variable und die wörtlichen Zahlen sind vom Typ int. Der int-Datentyp hat einen Maximalwert von 2 ^ 31 -1. Daher mit so großer Zahl, läuft der Datentyp int zu einer scheinbaren falschen Antwort führt.

Im ersten Beispiel wird die int nur zu lange auf Zuweisung an die Variable gefördert, die nach der Berechnung erfolgt. Das Ergebnis der Berechnung ist ein int.

Das zweite Beispiel, wirft den ersten Operanden zu einem langen, die Förderung der Berechnung auf eine lange verursacht. In diesem Fall ist das Ergebnis der Berechnung ein lange, wegen Förderung. Der lange Datentyp ist mehr als groß genug für die Berechnung ein.

Sie können daran interessiert zu wissen, dass dies in "Java Puzzlers" von Joshua Bloch und Neal Gafter bedeckt ist.


(Quelle: javapuzzlers.com )

Sie werden viele andere Java-Fallen, Fallen und Eckfällen in diesem Buch finden.

Ich bin mit der Starblue, der einen Kommentar verfasst. Anfügen eines L auf die Zahl.

Nein, es ist nicht offensichtlich.

Aber glauben Sie mir, nach einigen mehr Jahren Praxis und Beheben von Fehlern wie diese Sie sehr vernünftig geworden zu Integer-Überläufe und tun genau das Richtige, ohne auch nur darüber nachzudenken.

Es ist etwas, das jedem passiert. Definitiv kein Zeichen von schlechter Code Praxis, Ignoranz oder so.

Just zu den anderen Antworten hinzuzufügen, ich habe es hilfreich in der Vergangenheit gefunden Konstanten (public static final long) wie MILLISECS_DAY oder MILLISECS_HOUR zu definieren. Viel besser lesbar und nützlich.

Eine andere Möglichkeit, dies zu schreiben, ist

public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = (long) expireTimeInDays * 24 * 60 * 60 * 1000;
}

oder

public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = expireTimeInDays * 24L * 60 * 60 * 1000;
}

Wenn Sie FindBugs auf Ihrem Code verwenden, wird es genau dieses Problem erkennen. „ICAST: Ergebnis der Integer-Multiplikation zu lange gegossen.“ FindBugs' Beispiel ist genau das, was Sie tun; Tage in Millisekunden berechnet wird.

Dieses Problem mir nicht offensichtlich war das erste Mal, dass ich in ihn lief.

Es gibt einige statische Analyse-Tool (findbugs), die diese Art von Fehlern finden.

Numerische Mathematik auf Computer kann hart sein. Reihenfolge der Bedienung Fragen können Präzision und Genauigkeit in einer Weise beeinflussen, die Sie nicht erwarten. Datum Mathe kann auch überraschend schwierig sein. Oft ist es besser, eher die Datum / Kalender-Routinen zu verwenden, als zu versuchen, die Mathematik selbst zu tun, aber diese Routinen sind nicht die besten entwickelt, diejenigen in der Java-Klassenbibliothek.

Ich versuche nicht, meine Fehler zu rechtfertigen, aber es wäre toll, wenn die Java-Compiler klug genug sind, die int zu lange vor der Berechnung zu fördern (sobald die Berechnung auf eine Variable vom Typ zugeordnet wird, lang)

Übrigens, habe ich mit C / C ++ zu arbeiten, und wenn es ein C-Programm war, würde ich hatte das gleiche Problem, aber vor ein paar Jahren würde ich mit dieser Art von Operation vorsichtiger sein.

Ich werde mehr Aufmerksamkeit beim nächsten Mal (oder wechseln Sie zu Python) ...: D

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top