zoukankan      html  css  js  c++  java
  • java.lang基础数据类型boolean、char、byte、short、int、long、float、double (JDK1.8)

    java.lang.Boolean

    1     public static int hashCode(boolean value) {
    2         return value ? 1231 : 1237;
    3     }

    JDK 1.8新增一个hashCode方法,true的hashCode为1231,false的hashCode为1237, why?

    https://stackoverflow.com/questions/3912303/boolean-hashcode

    1     public static int compare(boolean x, boolean y) {
    2         return (x == y) ? 0 : (x ? 1 : -1);
    3     }

    在类中定义了两个public static final的变量,在创建Boolean对象的时候可以

    1     public static final Boolean TRUE = new Boolean(true);
    2     public static final Boolean FALSE = new Boolean(false);

    在创建Boolean对象的时候整个项目如果都是采用valueOf方法来创建,则整个项目就都会使用的这两个对象了。

    1     public static Boolean valueOf(boolean b) {
    2         return (b ? TRUE : FALSE);
    3     }
    4     public static Boolean valueOf(String s) {
    5         return parseBoolean(s) ? TRUE : FALSE;
    6     }

    剩下的Byte、Short、Integer、Long、Float、Double都是继承自Number类,除此之外还有BigDecimal和BigInteger类。

    下面总结下基础数据类型的数值范围

    数据类型 字节 范围
    boolean 1 true或false
    char 2 从字符型对应的整型数来划分,其表示范围是0~65535 
    byte 1 -128~127
    short 2 -32768~32767
    int 4 -2147483648~2147483647 (-2^31 ~ 2^31-1)
    long 8 -9223372036854775808 ~ 9223372036854775807
    float 4 -3.4E38~3.4E38 
    double 8 -1.7E308~1.7E308

    java.lang.Integer

     1     public static String toString(int i) {
     2         if (i == Integer.MIN_VALUE)
     3             return "-2147483648";
     4         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
     5         char[] buf = new char[size];
     6         getChars(i, size, buf);
     7         return new String(buf, true);
     8     }
     9 
    10     static void getChars(int i, int index, char[] buf) {
    11         int q, r;
    12         int charPos = index;
    13         char sign = 0;
    14 
    15         if (i < 0) {
    16             sign = '-';
    17             i = -i;
    18         }
    19 
    20         // Generate two digits per iteration
    21         while (i >= 65536) {
    22             q = i / 100;
    23         // really: r = i - (q * 100);
    24             r = i - ((q << 6) + (q << 5) + (q << 2));
    25             i = q;
    26             buf [--charPos] = DigitOnes[r];
    27             buf [--charPos] = DigitTens[r];
    28         }
    29 
    30         // Fall thru to fast mode for smaller numbers
    31         // assert(i <= 65536, i);
    32         for (;;) {
    33             q = (i * 52429) >>> (16+3);
    34             r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
    35             buf [--charPos] = digits [r];
    36             i = q;
    37             if (i == 0) break;
    38         }
    39         if (sign != 0) {
    40             buf [--charPos] = sign;
    41         }
    42     }
    43 
    44     final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE };
    45 
    46     // Requires positive x
    47     static int stringSize(int x) {
    48         for (int i=0; ; i++)
    49             if (x <= sizeTable[i])
    50                 return i+1;
    51     }
    52 
    53     final static char [] DigitTens = {
    54         '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
    55         '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
    56         '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
    57         '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
    58         '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
    59         '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
    60         '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
    61         '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
    62         '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
    63         '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
    64         } ;
    65 
    66     final static char [] DigitOnes = {
    67         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    68         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    69         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    70         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    71         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    72         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    73         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    74         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    75         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    76         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    77         } ;

    感觉这个toString方法实现的太巧妙了,为了减少运算真是无所不用其极,忍不住将这一整段的代码都贴出来了。

    stringSize方法是计算整个整数x有多少个字符,如此就可以预先计算出一个整型转换为字符数组要提前分配多少空间。这个方法的实现是通过比较大小实现的,预先定义好一个从小到大的数组sizeTable,配合下标确定size。

    getChars方法是将整型i转换为一个字符数组buf,其中index参数是整型i中包含的字符数,也即buf需要多少长度来存储转换后的整型。在方法中如果整型i >= 65536,则通过q = i/100;  r = i - q * 100;的方式将数字拆分成两个部分,其中r为i的前两位。高潮来了,看他怎么实现的获取这两位的字符的,竟然用数组查询的方式!当然,这是个while循环,会一直处理直到i<65536。再看下for循环中的将小于65536的数字转换为字符数组。q = (i * 52429) >>> (16+3) 这一句其实是个除以10的操作,那为什么要用52429呢?524288 = 2^19, i * 52429 然后无符号右移19位,相当于52429/2^19 = 0.100000381,近似是等于i/10(移位运算远比除法快,也是一种优化策略)。那为什么要选择2^19呢?参考了下知乎的回答:java源码中Integer.class中有个getChars方法,里面有个52429是怎么确定的?。然后我又计算了下2^20和2^21,结果竟然等于2^19,然后2^22精度就更高一些,但也没有太大的必要了。

     1     private static class IntegerCache {
     2         static final int low = -128;
     3         static final int high;
     4         static final Integer cache[];
     5 
     6         static {
     7             // high value may be configured by property
     8             int h = 127;
     9             String integerCacheHighPropValue =
    10                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    11             if (integerCacheHighPropValue != null) {
    12                 try {
    13                     int i = parseInt(integerCacheHighPropValue);
    14                     i = Math.max(i, 127);
    15                     // Maximum array size is Integer.MAX_VALUE
    16                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    17                 } catch( NumberFormatException nfe) {
    18                     // If the property cannot be parsed into an int, ignore it.
    19                 }
    20             }
    21             high = h;
    22 
    23             cache = new Integer[(high - low) + 1];
    24             int j = low;
    25             for(int k = 0; k < cache.length; k++)
    26                 cache[k] = new Integer(j++);
    27 
    28             // range [-128, 127] must be interned (JLS7 5.1.7)
    29             assert IntegerCache.high >= 127;
    30         }
    31 
    32         private IntegerCache() {}
    33     }
    34 
    35     public static Integer valueOf(int i) {
    36         if (i >= IntegerCache.low && i <= IntegerCache.high)
    37             return IntegerCache.cache[i + (-IntegerCache.low)];
    38         return new Integer(i);
    39     }

    通过IntegerCache内部类将常用的整数存储起来,当使用valueOf的方式构造Integer对象的时候,会直接从IntegerCache中取值。IntegerCache的最小值固定为-128,最大值可以通过java.lang.Integer.IntegerCache.high设置。

    java.lang.Byte

    在Byte类中同样是有个ByteCache缓存的缓存了从-128到正的127的byte,也就是byte的取值范围都被缓存了。通过下面的valueOf就可以使用到ByteCache类中的缓存值了。

    1     public static Byte valueOf(byte b) {
    2         final int offset = 128;
    3         return ByteCache.cache[(int)b + offset];
    4     }

    Byte中的很多函数都是将byte转换成int然后再操作的。 

    java.lang.Short

    Short类中也同样有个ShortCache缓存,缓存了从-128到127的整数,不过要注意short是两个字节的。同样的使用ValueOf可以使用缓存中的内容。

     1     private static class ShortCache {
     2         private ShortCache(){}
     3 
     4         static final Short cache[] = new Short[-(-128) + 127 + 1];
     5 
     6         static {
     7             for(int i = 0; i < cache.length; i++)
     8                 cache[i] = new Short((short)(i - 128));
     9         }
    10     }
    11 
    12     public static Short valueOf(short s) {
    13         final int offset = 128;
    14         int sAsInt = s;
    15         if (sAsInt >= -128 && sAsInt <= 127) { // must cache
    16             return ShortCache.cache[sAsInt + offset];
    17         }
    18         return new Short(s);
    19     }
    1     public static short reverseBytes(short i) {
    2         return (short) (((i & 0xFF00) >> 8) | (i << 8));
    3     }

    在Short类中还有个reverseBytes函数,将高位字节和低位字节互换位置。不知道这样做有什么用途。

    java.lang.Long

    同样的在Long类中toString方法实现类似于Integer中的toString方法,不再赘述。

    在缓存方面,Long类中同样有个LongCache缓存类,缓存了-128L~127L的Long对象,通过valueOf可以直接获取缓存中的类对象。

    在JDK 1.8中,增加了以下几个方法

     1     // 比较两个long
     2     // @since 1.7
     3     public static int compare(long x, long y) {
     4         return (x < y) ? -1 : ((x == y) ? 0 : 1);
     5     }
     6 
     7     // 比较两个unsigned long
     8     // @since 1.8
     9     public static int compareUnsigned(long x, long y) {
    10         return compare(x + MIN_VALUE, y + MIN_VALUE);
    11     }
    12 
    13     // 除法运算,结果是除得的结果,余数采用remainderUnsigned获得
    14     // @since 1.8
    15     public static long divideUnsigned(long dividend, long divisor) {
    16         if (divisor < 0L) { // signed comparison
    17             // Answer must be 0 or 1 depending on relative magnitude
    18             // of dividend and divisor.
    19             return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L;
    20         }
    21 
    22         if (dividend > 0) //  Both inputs non-negative
    23             return dividend/divisor;
    24         else {
    25             /*
    26              * For simple code, leveraging BigInteger.  Longer and faster
    27              * code written directly in terms of operations on longs is
    28              * possible; see "Hacker's Delight" for divide and remainder
    29              * algorithms.
    30              */
    31             return toUnsignedBigInteger(dividend).
    32                 divide(toUnsignedBigInteger(divisor)).longValue();
    33         }
    34     }
    35 
    36     // 除法运算,结果是余数
    37     // @since 1.8
    38     public static long remainderUnsigned(long dividend, long divisor) {
    39         if (dividend > 0 && divisor > 0) { // signed comparisons
    40             return dividend % divisor;
    41         } else {
    42             if (compareUnsigned(dividend, divisor) < 0) // Avoid explicit check for 0 divisor
    43                 return dividend;
    44             else
    45                 return toUnsignedBigInteger(dividend).
    46                     remainder(toUnsignedBigInteger(divisor)).longValue();
    47         }
    48     }

    另外增加了sum方法,如下面的代码,代码中并没有考虑溢出问题,所以谨慎调用。

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

    java.lang.Double

     1     public boolean equals(Object obj) {
     2         return (obj instanceof Double)
     3                && (doubleToLongBits(((Double)obj).value) ==
     4                       doubleToLongBits(value));
     5     }
     6 
     7     public static long doubleToLongBits(double value) {
     8         long result = doubleToRawLongBits(value);
     9         // Check for NaN based on values of bit fields, maximum
    10         // exponent and nonzero significand.
    11         if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
    12               DoubleConsts.EXP_BIT_MASK) &&
    13              (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
    14             result = 0x7ff8000000000000L;
    15         return result;
    16     }

    在Double类中,重载了equals方法,其中的doubleToRawLongBits是个native方法。

    java.lang.Float

    Float源码和Double类方法差不多。就这样结束吧。 

  • 相关阅读:
    Linux下退出vi编辑模式
    Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 17 declared in library(开发日志28)
    Could not download bmob-sdk.arr(cn.bmob.android:bmob-sdk:3.7.8)(开发日志25)
    本周总结
    思考概念方式
    面试体系目录
    2020面试记录
    日志
    redis 实现分布式锁
    SpringMvc servlet 拦截器 过滤器关系和区别及执行顺序
  • 原文地址:https://www.cnblogs.com/snowater/p/7662017.html
Copyright © 2011-2022 走看看