Java Integer 類 解讀

Integer 類是Java中最常用的類型,它是原生類型 int 的包裝類。在開發(fā)中我們基本可以將兩者等價。但是竖伯,最近在開發(fā)中遇到一個 ==equals 不一致的錯誤。所以趁此機會深入了解一下java中的Integer類因宇。

Integer的界限范圍與int類型是一致的七婴。都是 0x7fffffff~0x80000000。Integer類中是這樣聲明的察滑。

    /**
     * A constant holding the minimum value an {@code int} can
     * have, -2<sup>31</sup>.
     */
    public static final int   MIN_VALUE = 0x80000000;

    /**
     * A constant holding the maximum value an {@code int} can
     * have, 2<sup>31</sup>-1.
     */
    public static final int   MAX_VALUE = 0x7fffffff;

這兩個范圍大家經(jīng)常用打厘,一般不會出現(xiàn)問題。但是贺辰,由于補碼表示負數(shù)的關(guān)系户盯。正數(shù)總是比負數(shù)多一個來。作為邊界值饲化,這經(jīng)常會導致問題莽鸭。例如下面的代碼:

// Math.abs(int) 方法也是這個邏輯
int abs(int num) {
    return num < 0 ? -num : num;
}

這里返回結(jié)果不全是正數(shù),輸入Integer.MIN_VALUE的結(jié)果還是Integer.MIN_VALUE吃靠,因為沒有相應的補碼與之對應蒋川。所以在使用絕對值的時候還是要小心的,要考慮是否會出現(xiàn)一個Integer.MIN_VALUE的輸入撩笆,如果有可能捺球,那就需要更大范圍的類型(Long)來表示或者單獨對它進行處理。系統(tǒng)提供的abs方法并沒有考慮這個問題夕冲。

Integer 類可轉(zhuǎn)換的進制范圍: 2-36氮兵。 這兩個范圍參考Character.MIN_RADIXCharacter.MAX_RADIX兩個值。除了常用的二進制歹鱼、八進制泣栈、十六進制,其它在范圍內(nèi)的進制都可以十分方便地轉(zhuǎn)換輸出弥姻。
整個轉(zhuǎn)換的代碼如下:

    final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
        'o' , 'p' , 'q' , 'r' , 's' , 't' ,
        'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };
    public static String toString(int i, int radix) {

        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        if (radix == 10) {
            return toString(i);
        }

        char buf[] = new char[33];
        boolean negative = (i < 0);
        int charPos = 32;

        if (!negative) {
            i = -i;
        }

        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];

        if (negative) {
            buf[--charPos] = '-';
        }

        return new String(buf, charPos, (33 - charPos));
    }

這里需要注意的地方有:2-36 進制以外的進制都當十進制處理南片;十進制使用了默認的、更加快速的處理方法庭敦;這里數(shù)字的運算是使用負數(shù)參與計算的(while循環(huán)那里)疼进,個人感覺是因為負數(shù)的范圍比正數(shù)大,這樣不需要額外處理Integer.MIN_VALUE的問題秧廉,整個代碼變得簡潔很多伞广。

對于常見的二進制、八進制疼电、十六進制嚼锄,我們并不關(guān)心數(shù)字的符號,所以它提供了更加方便的接口蔽豺。代碼如下:

    public static String toHexString(int i) {
        return toUnsignedString(i, 4);
    }

    public static String toOctalString(int i) {
        return toUnsignedString(i, 3);
    }

    public static String toBinaryString(int i) {
        return toUnsignedString(i, 1);
    }

    private static String toUnsignedString(int i, int shift) {
        char[] buf = new char[32];
        int charPos = 32;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            buf[--charPos] = digits[i & mask];
            i >>>= shift;
        } while (i != 0);

        return new String(buf, charPos, (32 - charPos));
    }

這里的實現(xiàn)明顯要比上面的實現(xiàn)高效区丑,簡潔。

接下來就是最常用的toString()接口了修陡,他的實現(xiàn)用了一些高級的算法在里面沧侥。直接看代碼:

    final static char [] DigitTens = {
        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
        '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
        } ;

    final static char [] DigitOnes = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        } ;

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

    static void getChars(int i, int index, char[] buf) {
        int q, r;
        int charPos = index;
        char sign = 0;

        if (i < 0) {
            sign = '-';
            i = -i;
        }

        // Generate two digits per iteration
        while (i >= 65536) {
            q = i / 100;
        // really: r = i - (q * 100);
            r = i - ((q << 6) + (q << 5) + (q << 2));
            i = q;
            buf [--charPos] = DigitOnes[r];
            buf [--charPos] = DigitTens[r];
        }

        // Fall thru to fast mode for smaller numbers
        // assert(i <= 65536, i);
        for (;;) {
            q = (i * 52429) >>> (16+3);
            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
            buf [--charPos] = digits [r];
            i = q;
            if (i == 0) break;
        }
        if (sign != 0) {
            buf [--charPos] = sign;
        }
    }

    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

    // Requires positive x
    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }

這里從toString()方法開始看。先是對Integer.MIN_VALUE做了單獨的處理濒析。接下來轉(zhuǎn)成正數(shù)正什,開始主要的處理邏輯。主要邏輯以65536做為分界線号杏,分成了兩部分婴氮。大于65536的部分使用了除法,一次生成兩位十進制字符盾致;小于等于65536的部分使用了乘法加位移做成除以10的效果主经。下面的使用乘法的部分效率更高但是在16位以上的數(shù)字會存在溢出的問題,52429這個數(shù)字如果選得太小精度又會不夠庭惜,所以應該這里被迫只能分成了兩部分罩驻。整個過程使用生成字符都盡量避免運算,采用查表的的方式护赊』荻簦可以看出這里對細節(jié)的處理非常的多砾跃。

接下來是我們常用的pareseInt()方法:

    /**
     * Parses the string argument as a signed integer in the radix
     * specified by the second argument. 
     * <p>Examples:
     * <blockquote><pre>
     * parseInt("0", 10) returns 0
     * parseInt("473", 10) returns 473
     * parseInt("+42", 10) returns 42
     * parseInt("-0", 10) returns 0
     * parseInt("-FF", 16) returns -255
     * parseInt("1100110", 2) returns 102
     * parseInt("2147483647", 10) returns 2147483647
     * parseInt("-2147483648", 10) returns -2147483648
     * parseInt("2147483648", 10) throws a NumberFormatException
     * parseInt("99", 8) throws a NumberFormatException
     * parseInt("Kona", 10) throws a NumberFormatException
     * parseInt("Kona", 27) returns 411787
     * </pre></blockquote>
     *
     * @param      s   the {@code String} containing the integer
     *                  representation to be parsed
     * @param      radix   the radix to be used while parsing {@code s}.
     * @return     the integer represented by the string argument in the
     *             specified radix.
     * @exception  NumberFormatException if the {@code String}
     *             does not contain a parsable {@code int}.
     */
    public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        /*
         * WARNING: This method may be invoked early during VM initialization
         * before IntegerCache is initialized. Care must be taken to not use
         * the valueOf method.
         */

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

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

        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.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;
    }
    public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }

這里也是通過計算負數(shù)再添加符號位的方式避免Integer.MIN_VALUE單獨處理的問題。這里使用了一個mulmin變量來避免數(shù)字溢出的問題节吮,單純的使用正負號不能準確判斷是否溢出(一次乘法導致溢出的結(jié)果符號不確定)抽高。

接下來到了 IntegerCache 相關(guān)的內(nèi)容,代碼如下:

    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the -XX:AutoBoxCacheMax=<size> option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */


    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }
    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

在Integer類中有一個靜態(tài)內(nèi)部類透绩,它負責存儲了(high -low)個靜態(tài)Integer對象翘骂,并切在靜態(tài)代碼塊中初始化。low的值是固定的-128帚豪,high的默認值是127碳竟,如果不去配置虛擬機參數(shù),這個值不會變狸臣。配合valueOf(int) 方法莹桅,可以節(jié)省創(chuàng)建對象造成的資源消耗。

從注釋中可以看出 -XX:AutoBoxCacheMax=<size> 參數(shù)可以影響到緩存的大小固棚。
"java.lang.Integer.IntegerCache.high" 參數(shù)可以影響到high的值统翩。
自動裝箱時,如果值在cache中此洲,那么會直接返回cache中的對象不會額外創(chuàng)建一個對象厂汗。

這里就能解釋為什么一些自動裝箱的值會出現(xiàn)值不相等的情況,例如:

Integer a = 10;
Integer b = 10;
assert a == b // 沒問題呜师,他們對應緩存中的同一個對象地址

Integer c = 10000;
Integer d = 10000;
assert c == d // 不相等娶桦,他們沒有被緩存所以不是指向同一地址的
assert c.equals(d); // 沒問題,equals的本質(zhì)是值的比較

這里貼出Integer類的equals()方法 與 hashCode()方法的代碼:

    public int hashCode() {
        return value;
    }

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

符合預期汁汗。

接下來跳過幾個獲取系統(tǒng)屬性的方法衷畦。我們看它提供的幾個非常有意思的位操作的方法。

留下最高位
    public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);
        i |= (i >>  2);
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        return i - (i >>> 1);
    }
// 隨便一個例子知牌,不用管最高位之后有多少個1祈争,都會被覆蓋
// 00010000 00000000 00000000 00000000      raw
// 00011000 00000000 00000000 00000000      i | (i >> 1)
// 00011110 00000000 00000000 00000000      i | (i >> 2)
// 00011111 11100000 00000000 00000000      i | (i >> 4)
// 00011111 11111111 11100000 00000000      i | (i >> 8)
// 00011111 11111111 11111111 11111111      i | (i >> 16)
// 00010000 0000000 00000000 00000000       i - (i >>>1)
留下最低位
    public static int lowestOneBit(int i) {
        // HD, Section 2-1
        return i & -i;
    }
// 例子
// 00001000 10000100 10001001 00101000    i
// 11110111 01111011 01110110 11011000    -i
// 00000000 00000000 00000000 00001000  i & -i
數(shù)字開頭有多少個0
    public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        if (i == 0)
            return 32;
        int n = 1;
        if (i >>> 16 == 0) { n += 16; i <<= 16; }
        if (i >>> 24 == 0) { n +=  8; i <<=  8; }
        if (i >>> 28 == 0) { n +=  4; i <<=  4; }
        if (i >>> 30 == 0) { n +=  2; i <<=  2; }
        n -= i >>> 31;
        return n;
    }
// 方法很巧妙, 類似于二分法角寸。不斷將數(shù)字左移縮小范圍菩混。例子用最差情況:
// i: 00000000 00000000 00000000 00000001         n = 1
// i: 00000000 00000001 00000000 00000000         n = 17
// i: 00000001 00000000 00000000 00000000         n = 25
// i: 00010000 00000000 00000000 00000000         n = 29
// i: 01000000 00000000 00000000 00000000         n = 31
// i >>>31 == 0
// return 31
數(shù)字結(jié)尾有多少個0
    public static int numberOfTrailingZeros(int i) {
        // HD, Figure 5-14
        int y;
        if (i == 0) return 32;
        int n = 31;
        y = i <<16; if (y != 0) { n = n -16; i = y; }
        y = i << 8; if (y != 0) { n = n - 8; i = y; }
        y = i << 4; if (y != 0) { n = n - 4; i = y; }
        y = i << 2; if (y != 0) { n = n - 2; i = y; }
        return n - ((i << 1) >>> 31);
    }
// 與求開頭多少個0類似,也是用了二分法扁藕,先鎖定1/2, 再鎖定1/4沮峡,1/8,1/16亿柑,1/32邢疙。
// i: 11111111 11111111 11111111 11111111    n: 31
// i: 11111111 11111111 00000000 00000000    n: 15
// i: 11111111 00000000 00000000 00000000    n: 7
// i: 11110000 00000000 00000000 00000000    n: 3
// i: 11000000 00000000 00000000 00000000    n: 1
// i: 10000000 00000000 00000000 00000000    n: 0
1的位數(shù)
    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;
    }
// 具體例子參考維基百科,這里不再列舉

這是一個O(lgN)的算法,N代表i的bit數(shù)(這里N = 32)疟游。算法的具體內(nèi)容參考維基百科:Hamming weight
核心思想類似分治呼畸。

按bit旋轉(zhuǎn)
    public static int rotateLeft(int i, int distance) {
        return (i << distance) | (i >>> -distance);
    }
    public static int rotateRight(int i, int distance) {
        return (i >>> distance) | (i << -distance);
    }

這里我一開始沒有理解企蹭。尤其是shift操作符右面的參數(shù)是負數(shù)的情況行疏。后來一番搜索之后終于發(fā)現(xiàn),這里實質(zhì)上是利用了shift操作參數(shù)取值的技巧耙箍。shift操作符的定義參考這里聪廉。
重點看這里:

在左參數(shù)是int類型的時候,右參數(shù)只有低五位有效故慈;
在左參數(shù)是long類型的時候板熊,右參數(shù)只有低六位有效

我們列舉一下前幾個值就能發(fā)現(xiàn)規(guī)律:

distance -distance & 0x1F
0 0
1 31
2 30
3 29
... ...
1 31

所以有這么一個恒等式 distance + (-distance & 0x1F) = 32察绷。這不剛好用來做32位旋轉(zhuǎn)嘛干签。

這代碼雖然不好理解,但確實簡潔拆撼。

按bit逆置
    public static int reverse(int i) {
        // HD, Figure 7-1
        i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
        i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
        i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
        i = (i << 24) | ((i & 0xff00) << 8) |
            ((i >>> 8) & 0xff00) | (i >>> 24);
        return i;
    }

這個方法可以分成前后兩部分容劳。前半部分類似歸并排序,先把相鄰兩位逆置闸度,再把4位逆置竭贩,不斷擴展,直到每一個Byte內(nèi)部都逆置完畢莺禁。后半部分實質(zhì)上是一個按Byte逆置的過程留量。
前半部分比較難理解,這里提供一份可以打log的代碼哟冬,可以通過log查看它整個逆置的過程楼熄。有興趣的同學自行copy。

public void testReverse() {
    int number = 12345678;
    System.out.printf("%s  number\n\n", formatBinary(number));
    int a = (number & 0x55555555) << 1;
    System.out.printf("%s  (number & 0x55555555) << 1\n", formatBinary(a));
    int b = (number >>> 1) & 0x55555555;
    System.out.printf("%s  (number >>> 1) & 0x55555555\n", formatBinary(b));
    number = a | b;
    System.out.printf("%s  number\n\n", formatBinary(number));
    int c = (number & 0x33333333) << 2;
    System.out.printf("%s  (number & 0x33333333) << 2\n", formatBinary(c));
    int d = (number >>> 2) & 0x33333333;
    System.out.printf("%s  (number >>> 2) & 0x33333333\n", formatBinary(d));
    number = c | d;
    System.out.printf("%s  number\n\n", formatBinary(number));
}
static String formatBinary(int number) {
    char[] buff = new char[36];
    int mask = Integer.MIN_VALUE;
    int printer = 0;
    for (int i = 0; i < 32; i++) {
        if ((number & (mask >>> i)) != 0) buff[printer++] = '1';
        else buff[printer++] = '0';
        if (((i + 1) & 0x7) == 0) buff[printer++] = ' ';
    }
    return new String(buff);
}
判斷符號
    /**
     * Returns the signum function of the specified {@code int} value.  (The
     * return value is -1 if the specified value is negative; 0 if the
     * specified value is zero; and 1 if the specified value is positive.)
     *
     * @return the signum function of the specified {@code int} value.
     * @since 1.5
     */
    public static int signum(int i) {
        // HD, Section 2-7
        return (i >> 31) | (-i >>> 31);
    }

正常情況下浩峡,我們都是寫if語句的可岂。然而,真的可以不用翰灾。

按Byte逆置
    public static int reverseBytes(int i) {
        return ((i >>> 24)           ) |
               ((i >>   8) &   0xFF00) |
               ((i <<   8) & 0xFF0000) |
               ((i << 24));
    }

這里的代碼很熟悉缕粹。因為它就是 按bit逆置 的后半部分。

Integer類精彩的代碼就這些了预侯,讀過這一遍還是有很多收獲的致开。 有什么理解不對的地方還請大家指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萎馅,一起剝皮案震驚了整個濱河市双戳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌糜芳,老刑警劉巖飒货,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魄衅,死亡現(xiàn)場離奇詭異,居然都是意外死亡塘辅,警方通過查閱死者的電腦和手機晃虫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扣墩,“玉大人哲银,你說我怎么就攤上這事∩胩瑁” “怎么了荆责?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亚脆。 經(jīng)常有香客問我做院,道長,這世上最難降的妖魔是什么濒持? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任键耕,我火速辦了婚禮,結(jié)果婚禮上柑营,老公的妹妹穿的比我還像新娘屈雄。我一直安慰自己,他們只是感情好由境,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布棚亩。 她就那樣靜靜地躺著,像睡著了一般虏杰。 火紅的嫁衣襯著肌膚如雪讥蟆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天纺阔,我揣著相機與錄音瘸彤,去河邊找鬼。 笑死笛钝,一個胖子當著我的面吹牛质况,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玻靡,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼结榄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了囤捻?” 一聲冷哼從身側(cè)響起臼朗,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后视哑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绣否,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年挡毅,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒜撮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡跪呈,死狀恐怖段磨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情耗绿,我是刑警寧澤薇溃,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站缭乘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏琉用。R本人自食惡果不足惜堕绩,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邑时。 院中可真熱鬧奴紧,春花似錦、人聲如沸晶丘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浅浮。三九已至沫浆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滚秩,已是汗流浹背专执。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留郁油,地道東北人本股。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像桐腌,于是被迫代替她去往敵國和親拄显。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,961評論 6 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法案站,類相關(guān)的語法躬审,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法盒件,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗蹬碧。 張土汪:刷leetcod...
    土汪閱讀 12,743評論 0 33
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)炒刁,斷路器恩沽,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 1. 總是見過這種類似的話:“我不想爭罗心、不想搶,順其自然城瞎,是我的渤闷,別人搶不走;不是我的,強求也沒用脖镀§” 可能有很多...
    柑橘與檸檬呢閱讀 390評論 0 3