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

基本变量类型

2017-01-02

阅读:


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

一、基本类型

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

1.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;
    }
    ...
}

2.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.不可变对象天生就是线程安全的他们可以自由的在多线程多线程之间共享不需要任何同步处理 --> 线程安全高效

3.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;
    }
}

字符串长度限制:

1.编译期:65534 (字符串常量池限制、Java规范)

2.运行期:4G (int 范围)

参考

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