不管是java还是其他语言,都会有基本数据类型,这种类型更加方便常用。
在java中,基本数据类型直接存储在堆栈中
java有八种基本数据类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型
基本类型 | 大小 | 最小值 | 最大值 | 包装器类型 |
boolean | -- | -- | -- | Boolean |
char | 16-bit | \u0000(即为0) | \uffff(即为65,535) |
Character |
byte | 8 bits | -128 | +127 | Byte |
short | 16 bits | -2^15 | +2^15-1 | short |
int | 32 bits | -2^31 | +2^31-1 | Integer |
long | 64 bits | -2^63 | +2^63-1 | Long |
float | 32 bits | IEEE754 | IEEE754 | Float |
double | 64 bits | IEEE754 | IEEE754 | Double |
boolean
boolean类型只有两个值,true和false,包装类型是Boolean,里面的hashcode方法是
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
char
char是字符类型,有如下几种定义方式,可以用单引号直接定义,也可以用在char的取值范围内的数字定义,还可以用十六进制定义,还有就是用'\uxxxx'的形式定义
char c1 = 'a'; //char 0 - 2^16-1
char c2 = '中';
char c3 = 20013;
char c4 = 0x4e2d;
char c5 = '\u4e2d';
//char c4 = -1;
System.out.println("next is about char ");
System.out.println("==c1:"+Integer.toBinaryString(c1)+"==c2:"+Integer.toBinaryString(c2)+"==c4:"+Integer.toBinaryString(c4));
System.out.println("===c1:"+c1+"===c2:"+c2+"===c1:(int)"+(int)c1+"===c2:(int)"+(int)c2+"===c3:"+c3+"===c4:"+c4+"===c5:"+c5);
System.out.println(Character.hashCode(c1)+"=="+Character.hashCode(c2)+"=="+Character.hashCode(c3)+"=="+Character.hashCode(c4)+"=="+Character.hashCode(c5));
输出结果为
next is about char
==c1:1100001==c2:100111000101101==c4:100111000101101
===c1:a===c2:中===c1:(int)97===c2:(int)20013===c3:中===c4:中===c5:中
97==20013==20013==20013==20013
上面可以得知不同的定义方式定义同一个字符结果是一样的,Character的hashcode方法得到的结果是它转为int的结果
//character的hashCode源码
public static int hashCode(char value) {
return (int)value;
}
byte
byte是由8位二进制组成的带符号的最小的数字类型。这里要说一下bit和byte的区别。
bit(比特)是表示信息的最小单位,就是一个二进制的的一位
byte由8 bit组成,是数据存储的基础单位,1Byte又称为一个字节,用一个字节(Byte)储存,可区别256个数字。
short
短整型,长度只有int型二分之一,节省空间
int
整型,32位,一般整型默认为int型
byte,short,int的hashcode都是转为int型的本身
//short,byte,int
public static int hashCode(char value) {
return (int)value;
}
它们三个可以看作都是类似的,在范围内都可以互相转换。都可以通过Integer.toBinaryString(xxx)查看二进制
byte by = 'a';
System.out.println("next is about byte ");
System.out.println(Byte.hashCode(by));
System.out.println(by);
System.out.println(Integer.toBinaryString(by));
short s = 1;
short s1 = -1;
System.out.println("next is about short ");
System.out.println(Integer.toBinaryString(s)+"=="+Integer.toBinaryString(s1));
System.out.println(Short.hashCode(s)+"=="+Short.hashCode(s1));
int i = 120;
int i1 = -1;
System.out.println("next is about int ");
System.out.println(Integer.toBinaryString(i)+"=="+Integer.toBinaryString(i1));
System.out.println(Integer.hashCode(i)+"=="+Integer.hashCode(i1));
next is about byte
97
97
1100001
next is about short
1==11111111111111111111111111111111
1==-1
next is about int
1111000==11111111111111111111111111111111
120==-1
long
长整型,64位,它的hashcode是将值无符号右移32位再与本身异或得到的值,定义大于int型的数时需在后面加个l/L
/**
* Returns a hash code for a {@code long} value; compatible with
* {@code Long.hashCode()}.
*
* @param value the value to hash
* @return a hash code value for a {@code long} value.
* @since 1.8
*/
public static int hashCode(long value) {
return (int)(value ^ (value >>> 32));
}
float
单精度浮点类型,32位组成,第一位是符号位,0表示正数。后八位是指数位,用来存储科学计数法中的指数数据,并且采用移位存储。最后23位数是尾数部分
如下三个数。1.5转为二进制数是1.1*2^0,指数位是0,第2-9位就是127+0也就是0111 1111 (指数计算需加上127)
小数点转为二进制是将其*2看其是否大于1,如大于1,则二进制数唯一,否则为0,大于1后取小数部分继续*2
float的hashcode最后是native函数。
这里介绍下native修饰符:
总所周知java是一门跨平台语言,java的跨平台是怎么实现的呢,就是这个native关键字。native关键字的函数都是操作系统实现的, java只能调用,所以java的底层实际上就是在不同的平台上调用不同的native方法实现对操作系统的访问的。当我们看java源码的时候看到这个native就知道这个已经不是java语言能干的事了。
float f = 1.5f; // 0 0111 1111 1000 0000 0000 .... 直到一共32位 3fc00000
float f1 = -1.3f; // 1 0111 1111 0100 1100 1100 1100 .... 直到一共32位 bfa66666
float f2 = -100.3f; // 1 1000 0101 1001 0001 0011 0011 .... 直到一共32位 0110 0100.0100 1100 1100 1100
float f3 = 0xC2C89999;
float f4 = 0x3fc00000;
System.out.println("next is about float ");
System.out.println(Float.toHexString(f)+"=="+Float.toHexString(f1)+"=="+Float.toHexString(f2));
System.out.println(Float.hashCode(f)+"=="+Float.hashCode(f1)+"=="+Float.hashCode(f2));
System.out.println(f3+"==="+f4+"=="+Float.intBitsToFloat(Integer.parseInt("3fc00000",16)));
结果中可以看到想将二进制转为其本身可以用Float.intBitsToFloat(Integer.parseInt("3fc00000",16))的方法,不过此方法受限于parseInt。直接使用二进制表示不出想要的浮点数。
next is about float
0x1.8p0==-0x1.4cccccp0==-0x1.913334p6
1069547520==-1079613850==-1027040870
-1.0270409E9===1.06954752E9==1.5
double
双精度浮点类型,64位。与单精度类似,第一位是符号位,不过指数位有11位,最后52位数尾数部分
计算也与单精度类似,不过指数位是加上1023这个偏差值,毕竟他是11位。
它的hashcode简单的讲就跟long的差不多,不过是多了long bits = doubleToLongBits(value);这个最后也是个native修饰符
/**
* Returns a hash code for a {@code double} value; compatible with
* {@code Double.hashCode()}.
*
* @param value the value to hash
* @return a hash code value for a {@code double} value.
* @since 1.8
*/
public static int hashCode(double value) {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
包装类
每个基本类型都有其包装类,我们知道java的一种思想就是一切皆对象,那么包装类的作用就是将基本数据类型转为一个对象
Integer i = 2;//装箱
int j = i;//拆箱
看下面一段代码
Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x==y); //false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z==k); //true
Integer i1 = Integer.valueOf(128);
Integer i2 = Integer.valueOf(128);
System.out.println(i1==i2); //false
第一个new是新建了一个对象,所以两个不同。第二个一样,那第三个怎么不一样?原因是Integer.valueOf()会先判断值是否在缓冲池中,在的话直接返回缓冲池的内容,不是再新建个。Integer的缓冲池大小是-128到127。还有就是java9后就不建议使用new Integer()的方法。可以看到下方源码建议我们使用valueOf的方法。而且valueOf中@HotSpotIntrinsicCandidate这个注解在HotSpot中都有一套高效的实现,该高效实现基于CPU指令
/**
* Constructs a newly allocated {@code Integer} object that
* represents the specified {@code int} value.
*
* @param value the value to be represented by the
* {@code Integer} object.
*
* @deprecated
* It is rarely appropriate to use this constructor. The static factory
* {@link #valueOf(int)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
@Deprecated(since="9")
public Integer(int value) {
this.value = value;
}
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
VM.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
关于缓冲池Boolean是true和false,四个整数型(Byte,Short,Integer,Long)都是-128到127。 Character是\u0000 到 \u007F