[JAVA] Ich habe die Quelle von Long gelesen

Irgendwie habe ich beschlossen, auch die JDK-Quelle zu lesen. Trotzdem habe ich keine Zeit, jede Zeile sorgfältig zu lesen, also habe ich sie kurz gelesen und diesen Code gefunden. Das letzte Mal ich habe die Quelle von Integer gelesen, also wird das nächste Long sein.

Lange Klasse

Die Long-Klasse ist eine Wrapper-Klasse für den primitiven Typ long. Erstens Felder und Konstruktoren. Nun, es ist eine Quelle, die sich jeder vorstellen kann.

Long.java


    private final long value;

    public Long(long value) {
        this.value = value;
    }

LongCache-Klasse

Tatsächlich gibt es eine LongCache-Klasse, die in Javadoc nicht angezeigt wird.

Long.java


    private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

Wenn ich denke, dass Long auch ein externer Parameter wie Integer ist, wurde er von -128 auf 127 festgelegt. Ich habe nichts im Original geschrieben, nicht unkommentiert und zitiert. Dies ist seit JDK 1.5 der Fall, daher scheint Oracle nicht relevant zu sein.

Es ist ein Cache von LongCache, auf den jedoch von valueOf verwiesen wird.

Long.java


    public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }

Ich dachte, ich würde es mit dem Vergleichsoperator == vergleichen, aber es ist dasselbe wie Byte, Short und Integer.

Hacker's Delight-Quelle

Es ist auch in Integer. Die funktionalen waren die gleichen, als ich dachte, sie wären zusammen, aber die Implementierung war etwas anders. Es ist natürlich, weil es sich von 32-Bit und 64-Bit unterscheidet.

Integer.java


    public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

Long.java


     public static int bitCount(long i) {
        // HD, Figure 5-14
        i = i - ((i >>> 1) & 0x5555555555555555L);
        i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
        i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        i = i + (i >>> 32);
        return (int)i & 0x7f;
     }

Da die Bitbreite unterschiedlich ist, ändert sich die Konstante. Nun, Abbildung 5-2 und Abbildung 5-14. Entweder ist einer falsch. Wenn Sie wie Mr. Knoose Typo $ 2,56 bezahlen würden, würde ich gründlich danach suchen.

Summenmethode, Max-Methode, Min-Methode

Ab JDK 1.8 wurden sum, max, min hinzugefügt, die nicht den gleichen Wert wie Integer haben. Ich dachte nicht, dass ich Byte und Short übersprungen hätte.

Long.java


    public static long sum(long a, long b) {
        return a + b;
    }

    public static long max(long a, long b) {
        return Math.max(a, b);
    }

    public static long min(long a, long b) {
        return Math.min(a, b);
    }

Ich habe es in Integer geschrieben, aber wenn sum eine Methode mit Überlauferkennungsfunktion ist, ist es immer noch sinnvoll. Zum Beispiel dachte ich, es wäre professionell, wenn es eine lange Überlauferkennung mit Mehrfachmultiplikation anstelle von Summe gäbe. Die Überlauferkennung kann mit long durch Multiplikation von int berechnet werden, die Überlauferkennung durch Multiplikation mit long ist jedoch problematisch.

Es tut mir leid, dass beiläufig @see java.util.function.BinaryOperator steht. Ich weiß nicht, wie sie zusammenhängen.

Konstante

Konstanten werden für Byte, Short, Integer und Long definiert. Es gibt fünf MIN_VALUE, MAX_VALUE, TYPE, SIZE, BYTES, und die vorherigen drei stammen aus der Antike, wobei SIZE ab JDK 1.5 und BYTES ab JDK 1.8 hinzugefügt wurden. Nun, ich benutze nur MIN_VALUE und MAX_VALUE.

Byte.java


    public static final byte   MIN_VALUE = -128;
    public static final byte   MAX_VALUE = 127;

Short.java


    public static final short   MIN_VALUE = -32768;
    public static final short   MAX_VALUE = 32767;

Integer.java


    @Native public static final int   MIN_VALUE = 0x80000000;
    @Native public static final int   MAX_VALUE = 0x7fffffff;

Long.java


    @Native public static final long MIN_VALUE = 0x8000000000000000L;
    @Native public static final long MAX_VALUE = 0x7fffffffffffffffL;

Es ist eine Quelle, die es dem Menschen leicht macht zu verstehen, wo eine große Anzahl erkannt wird. Ich wünschte, ich hätte alle Hexadezimalzahlen. Als ich mir jedoch die Quelle ansah, dachte ich, dass int und long der Maximalwert in Dezimalzahl sein sollten, und es stellte sich heraus, dass es Ghan war. Im Javadoc gibt es konstante Feldwerte, aber sie sind 2147483647 und 9223372036854775807L.

hashCode-Methode

Die Hash-Berechnungslogik wurde seit JDK 1.8 in statischen Methoden implementiert. Bis JDK 1.7 wurde die Logik in einer normalen Methode geschrieben.

Long.java


    public int hashCode() {
        return Long.hashCode(value);
    }

    public static int hashCode(long value) {
        return (int)(value ^ (value >>> 32));
    }

Bei der Überlegung, wie 64 Bit zu 32 Bit verarbeitet werden sollen, war dies eine exklusive logische Summe (XOR) zwischen den oberen und unteren 32 Bit.

toString-Methode

Dies ist eine alte Methode.

Long.java


    public static String toString(long i) {
        if (i == Long.MIN_VALUE)
            return "-9223372036854775808";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }

Die Verarbeitung zum Zeitpunkt von Long.MIN_VALUE ist ziemlich schwierig. Wenn es negativ ist, ist der Absolutwert um 1 größer, was auf verschiedene Weise problematisch ist. Eigentlich mache ich mit getChars eine Zeichenkette, aber es ist ein Pfad, weil es schwierig ist, die Quelle zu betrachten.

Wenn Sie an Integer.toString denken,

Integer.java


    public static String toString(int i) {
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
    }

Was machst du auch Was ist also mit Short und Byte?

Short.java


    public static String toString(short s) {
        return Integer.toString((int)s, 10);
    }

Byte.java


    public static String toString(byte b) {
        return Integer.toString((int)b, 10);
    }

Wie erwartet riefen diese Integer.toString auf.

parseLong-Methode

Dies ist eine alte Methode.

Long.java


    public static long parseLong(String s, int radix)
              throws NumberFormatException
    {
        if (s == null) {
            throw new NumberFormatException("null");
        }

        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }

        long result = 0;
        boolean negative = false;
        int i = 0, len = s.length();
        long limit = -Long.MAX_VALUE;
        long multmin;
        int digit;

        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {
                    negative = true;
                    limit = Long.MIN_VALUE;
                } else if (firstChar != '+')
                    throw NumberFormatException.forInputString(s);

                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }

Das Überprüfen von NumberFormatException ist in Ordnung. Es gibt auch einen Nur-Nur-Scheck.

Wenn Sie denken, dass es in Ordnung ist, einen kurzen Blick darauf zu werfen, ziehen Sie mit result- = digit; Wenn Sie denken, dass es sich um eine Addition handelt, geben Sie ein negatives Ergebnis zurück: -Ergebnis: und das Vorzeichen ist entgegengesetzt. Ich frage mich, ob das Minus ist, weil der absolute Wert 1 größer ist.

Wenn Sie sich fragen, was ist, wenn (Ergebnis <Grenze + Ziffer) ist, führen Sie Ergebnis -digit aus und bringen Sie es auf die rechte Seite, um den Bereich zu überprüfen, damit der Absolutwert nicht überläuft? Wenn ich es schreibe, ziehe ich es vorerst heraus, und wenn der Wert, der negativ sein sollte, positiv wird, wird es als Überlauf beurteilt.

parseUnsignedLong-Methode

Eine Methode namens parseUnsignedInt wurde seit JDK 1.8 zu Integer hinzugefügt, aber auch zu Long. Ist Java nicht lange signiert? Was bedeutet es, es ohne Vorzeichen zu analysieren?

Long.java


    public static long parseUnsignedLong(String s, int radix)
                throws NumberFormatException {
        if (s == null)  {
            throw new NumberFormatException("null");
        }

        int len = s.length();
        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar == '-') {
                throw new
                    NumberFormatException(String.format("Illegal leading minus sign " +
                                                       "on unsigned string %s.", s));
            } else {
                if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
                    (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
                    return parseLong(s, radix);
                }

                // No need for range checks on len due to testing above.
                long first = parseLong(s.substring(0, len - 1), radix);
                int second = Character.digit(s.charAt(len - 1), radix);
                if (second < 0) {
                    throw new NumberFormatException("Bad digit at end of " + s);
                }
                long result = first * radix + second;
                if (compareUnsigned(result, first) < 0) {
                    /*
                     * The maximum unsigned value, (2^64)-1, takes at
                     * most one more digit to represent than the
                     * maximum signed value, (2^63)-1.  Therefore,
                     * parsing (len - 1) digits will be appropriately
                     * in-range of the signed parsing.  In other
                     * words, if parsing (len -1) digits overflows
                     * signed parsing, parsing len digits will
                     * certainly overflow unsigned parsing.
                     *
                     * The compareUnsigned check above catches
                     * situations where an unsigned overflow occurs
                     * incorporating the contribution of the final
                     * digit.
                     */
                    throw new NumberFormatException(String.format("String value %s exceeds " +
                                                                  "range of unsigned long.", s));
                }
                return result;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
    }

Wenn Sie es um eine Ziffer reduzieren und analysieren und es beim Hinzufügen der letzten Ziffer verringert, fühlt es sich wie ein Überlauf an. Es analysiert unsigniert, kann aber negativ sein. Es ist eine großartige Spezifikation.

Lass es uns versuchen.

Main.java


	public static void main(String[] args) {
        long l01 = Long.parseUnsignedLong("9223372036854775807");
        System.out.println(l01);
        long l02 = Long.parseUnsignedLong("9223372036854775808");
        System.out.println(l02);
        long l03 = Long.parseUnsignedLong("18446744073709551615");
        System.out.println(l03);
        long l04 = Long.parseUnsignedLong("18446744073709551616");
        System.out.println(l04);
    }

Wenn du rennst ...

9223372036854775807
-9223372036854775808
-1
Exception in thread "main" java.lang.NumberFormatException: String value 18446744073709551616 exceeds range of unsigned long.
	at java.lang.Long.parseUnsignedLong(Long.java:719)
	at java.lang.Long.parseUnsignedLong(Long.java:746)
	at Main.main(Main.java:28)

Das Ergebnis ist wie erwartet, aber sind Sie glücklich? Dies. Wenn Sie 64-Bit voll verwenden möchten, können Sie BigInteger verwenden.

Schließlich

In der Vergangenheit war 32-Bit der Standard, sodass Sie sehen können, dass 32-Bit-Int und 64-Bit-Länge separat implementiert werden. Wenn es lang ist, scheint die Verarbeitung schwer zu sein. In 64-Bit-Betriebssystemen wird derzeit im Allgemeinen eine 64-Bit-VM verwendet, und in Bezug auf die Hardware scheint 64-Bit-Länge normal zu funktionieren. Im Fall von Intel x64 ist das Allzweckregister beispielsweise 8-Bit-Register: AH AL BH BL CH CL DH DL 16-Bit-Register: AX BX CX DX 32-Bit-Register: EAX EBX ECX EDX 64-Bit-Register: RAX RBX RCX RDX R8 R9 R10 R11 R12 R13 R14 R15 Jetzt nimmt die Anzahl der 64-Bit-Register so stark zu!

Ich bin der Meinung, dass die Bytecode-Spezifikationen der aktuellen JVM auf 32 Bit basieren, daher denke ich, dass ich sie beim nächsten Mal auf 64 Bit aktualisieren und lange, lange 128 Bit erstellen kann.

Recommended Posts

Ich habe die Quelle von Long gelesen
Ich habe die Quelle von ArrayList gelesen, die ich gelesen habe
Ich habe die Quelle von Integer gelesen
Ich habe die Quelle von Short gelesen
Ich habe die Quelle von Byte gelesen
Ich habe die Quelle von String gelesen
Ich habe das Kotlin-Startbuch gelesen
Ist drainTo von LinkedBlockingQueue sicher? Ich bin der Quelle gefolgt
05. Ich habe versucht, die Quelle von Spring Boot zu löschen
Ich habe die interne Verarbeitung von Retrofit untersucht
[Tag: 5] Ich habe die Grundlagen von Java zusammengefasst
Ich habe die Grundlagen der Zeicheneingabe verstanden
Ich habe die Eigenschaften von Java und .NET verglichen
Ich möchte den Inhalt der Absicht var_dump
Ich habe versucht, den Profiler von IntelliJ IDEA zu verwenden
Ich habe die Anzahl der Taxis mit Ruby überprüft
Probieren Sie Progate Free Edition [Java I]
[Java] So erhalten Sie die URL der Übergangsquelle
Ich habe versucht, die Server-Push-Funktion von Servlet 4.0 zu verwenden
Ich habe den lesbaren Code gelesen, machen Sie sich also eine Notiz
Ich war süchtig nach der Aufzeichnung des zugehörigen Modells
Ich habe die Listenansicht der Android-Entwicklung gemeinsam gesehen
Ich habe versucht, die Kapazität von Spring Boot zu reduzieren
Beurteilung des Kalenders
Ich habe den neuen Feature-Profiler von IntelliJ IDEA 2019.2 ausprobiert.
Die Welt der Clara-Regeln (4)
Ich möchte die Antwort der Janken-App wissen
Bildverarbeitung: Grundstruktur des vom Programm gelesenen Bildes
Ich möchte den Namen des Posters des Kommentars anzeigen
Ich habe das Anzeigeformat der JSON-Antwort von Rails zusammengefasst
Die Welt der Clara-Regeln (1)
Die Welt der Clara-Regeln (3)
Lesen Sie die Java HashMap-Quelle
Ich habe den "Object-Oriented Practice Guide" gelesen, also ein Memorandum
Quelle zellulärer Objekte
Lesen Sie das Rails-Handbuch erneut (Übersicht über Action Controller).
[Java] Beim Schreiben der Quelle ... Memorandum ①
Ich habe ein Sequenzdiagramm des j.u.c.Flow-Beispiels geschrieben
Die Welt der Clara-Regeln (5)
Ich habe die Typen und Grundlagen von Java-Ausnahmen zusammengefasst
Die Idee der schnellen Sortierung
Ich bin mir der Bequemlichkeit des Graphql-Code-Generators Teil 2 sehr bewusst
Ich kann den Bildschirm der Rails-Datenbankkonsole nicht verlassen
Ich möchte die Bildlaufposition von UITableView zurückgeben!
Die Idee von jQuery
Ich habe die Serverseite des Online-Kartenspiels gemacht made
Ich habe das Verhalten von Java Scanner und .nextLine () nicht wirklich verstanden.
Ich habe einen Blick in die Java HashMap geworfen
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
[Android] Beenden Sie die Aktivität der Übergangsquelle zum Zeitpunkt des Bildschirmübergangs
Ich möchte die Protokollausgabeeinstellung von UtilLoggingJdbcLogger ändern