没长正的技术专栏 勤动手、多思考

基本变量类型

2017-01-02

阅读:


Integer、Short、Float、Long、BigDecimal、String 简单分析 (JDK8+)

基本类型

数据类型(Integer、Short、Float、Long、BigDecimal)都继承Number,实现了Comparable接口,都有HashCode、ToString()方法<略>、equals()方法<略>、不可变类(final)、 各种类型转换、解析的方法。

HashCode

Short、Integer HashCode 值本身

由源码可知:

//Short HashCode
public final class Short extends Number implements Comparable<Short> {
    public int hashCode() {
        return hashCode(this.value);
    }
    public static int hashCode(short var0) {
        return var0;
    }
    ...
}

//Integer HashCode
public final class Integer extends Number implements Comparable<Integer> {
    public int hashCode() {
        return hashCode(this.value);
    }
    public static int hashCode(int var0) {
        return var0;
    }
    ...
}

Short与Integer HashCode为对象自身的value值。

测试结果:

public class HashCodeTest {
    public static void main(String[] args) {
        Integer integer = new Integer(100);
        System.out.println(" Integer " + integer + " HashCode is :" + integer.hashCode());

        short s = 100;
        Short sVar = new Short(s);
        System.out.println(" Short " + sVar + " HashCode is :" + sVar.hashCode());
    }
}
 //结果:
 Integer 100 HashCode is :100
 Short 100 HashCode is :100

Float、Long、BigDecimal 的HashCode 根据各自的规则变化

由源码可知:

//Float HashCode
public final class Float extends Number implements Comparable<Float> {
    @Override
    public int hashCode() {
        return Float.hashCode(value);
    }
    /**
     * @since 1.8
     */
    public static int hashCode(float value) {
        return floatToIntBits(value);
    }
    public static int floatToIntBits(float value) {
        int result = floatToRawIntBits(value);//底层native方法
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & FloatConsts.EXP_BIT_MASK) ==
              FloatConsts.EXP_BIT_MASK) &&
             (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
            result = 0x7fc00000;
        return result;
    }
    ...
}

//Long HashCode
public final class Long extends Number implements Comparable<Long> {
    @Override
    public int hashCode() {
        return Long.hashCode(value);
    }
    /**
     * @since 1.8
     */
    public static int hashCode(long value) {
        return (int)(value ^ (value >>> 32));//(Long 8个字节,64位)向右移32位,即去高位,然后指数次方
    }
    ...
}

//BigDecimal (2.0 和2.00 hashCode same)  
//为什么采用的31的倍数  --> 
//1.31为素数。
//2.31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化,使用31的原因可能是为了更好的分配hash地址,并且31只占用5bits!
public class BigDecimal extends Number implements Comparable<BigDecimal> {
    @Override
    public int hashCode() {
        if (intCompact != INFLATED) {
            long val2 = (intCompact < 0)? -intCompact : intCompact;
            int temp = (int)( ((int)(val2 >>> 32)) * 31  +
                              (val2 & LONG_MASK));
            return 31*((intCompact < 0) ?-temp:temp) + scale;
        } else
            return 31*intVal.hashCode() + scale;
    }
    ...
}

//String hashCode  31
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     *  数学表达式:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.) --> 空字符串的hash为0
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
    ...
}

Cache

为了提高性能,做了缓存优化(@Since 1.5 代码中发现的),ShortIntegerLongString

由源码分析可知: FloatBigDecimal无缓存

//Short 私有静态内部类 范围:-128 ~ 127 之间
public final class Short extends Number implements Comparable<Short> {
    private static class ShortCache {
            static final Short[] cache = new Short[256];

            private ShortCache() {
            }

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

            }
        }
    ...
}

//Integer 私有静态内部类 默认范围:-128 ~ 127,可通过VM设置范围:-128 ~ 2147483518
public final class Integer extends Number implements Comparable<Integer> {
    private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer[] cache;
            private IntegerCache() {
            }
            static {
                int var0 = 127;
                String var1 = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                int var2;
                if (var1 != null) {
                    try {
                        var2 = Integer.parseInt(var1);
                        var2 = Math.max(var2, 127);
                        var0 = Math.min(var2, 2147483518);
                    } catch (NumberFormatException var4) {
                        ;
                    }
                }

                high = var0;
                cache = new Integer[high - -128 + 1];
                var2 = -128;
                for(int var3 = 0; var3 < cache.length; ++var3) {
                    cache[var3] = new Integer(var2++);
                }
                assert high >= 127;
            }
        }
}

//Long 私有静态内部类 范围:-128 ~ 127 之间
public final class Long extends Number implements Comparable<Long> {
    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);
            }
        }
    ...
}

//String 字符串常量池
jdk1.6下字符串常量池是在永久区中
jdk1.7,1.8下字符串常量池已经转移到堆中了,是堆中的一部分内容

//注意:不可变性分析
1.如果你需要一个可修改的字符串,应该使用StringBuilder StringBuffer,否则会有大量的时间浪费在垃圾回收上,每次试图修改都会有新的String对象被创建。
2.不可变对象天生就是线程安全的,他们可以自由的在多线程多线程之间共享,不需要任何同步处理。 --> 线程安全、高效

String equals()简单分析

由源码分析:验证字符是否相等:1.类型是否相同 2. 长度是否相同 3.比较具体的值

public boolean equals(Object var1) {
    if (this == var1) {
        return true;
    } else {
        if (var1 instanceof String) {
            String var2 = (String)var1;
            int var3 = this.value.length;
            if (var3 == var2.value.length) {
                char[] var4 = this.value;
                char[] var5 = var2.value;

                for(int var6 = 0; var3-- != 0; ++var6) {
                    if (var4[var6] != var5[var6]) {
                        return false;
                    }
                }

                return true;
            }
        }

        return false;
    }
}

参考:

https://docs.oracle.com/javase/8/docs/api/

http://www.hollischuang.com/archives/99

http://www.hollischuang.com/archives/1230 Java中字符串的不变性

https://www.cnblogs.com/tongkey/p/8587060.html 字符串常量池案例分析


欢迎拍砖,多多交流,转载请注明出处:[没长正的技术专栏](http://blog.meizhangzheng.com) 如涉及侵权问题,请发送邮件到xsj34567@163.com,如情况属实本人将会尽快删除。


上一篇 Java 学习路线

下一篇 常用集合-Set

Comments

Content