Integer、Short、Float、Long、BigDecimal、String 简单分析 (JDK8+)
一、基本类型
数据类型(Integer、Short、Float、Long、BigDecimal)都继承Number,实现了Comparable
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 代码中发现的),Short
、Integer
、Long
、String
由源码分析可知: Float
、BigDecimal
无缓存
//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 字符串常量池案例分析