Java数据类型和包装类型


一、Java中有哪些基本数据类型?

基本数据类型 位数 字节 默认值 取值范围
byte 8 1 0 -128~127
short 16 2 0 -3276832767(-2^152^15-1)
int 32 4 0 -2147483648~2147483647
long 64 8 0L -92233720368547758089223372036854775807(-2^632^63-1)
char 16 2 ‘u0000’ 065535(02^16-1)
float 32 4 0f 3.4e-38~3.4e38
double 64 8 0d 1.7e-308~1.7e308
boolean 1 false true、false

为什么有的最大值都需要-1?:因为在二进制补码中,最高位是用来表示符号的(0表示整数、1表示负数)。所以我们要表示最大的整数,需要把除了最高位之外的所有位都设为1(如果再加1,就会溢出,变成负数)

其他注意点

  • 在Java中long类型的数值需要在后面加上L,否则会被视作int解析
  • char a = 'h'用到的是单引号,String s = "hi"用到的是双引号

二、基本数据类型和包装类型有什么区别?

基本数据类型对应的包装类型如下:

基本数据类型 包装类型
byte Byte
short Short
int Integer
long Long
char Char
float Float
double Double
boolean Boolean

基本数据类型和包装类型的区别如下:

  • 默认值:基本数据类型都有对应的默认值,而包装类型默认为null
  • 比较方式:基本数据类型通过==比较值,包装类型通过equals比较值(包装类型通过==比较的是对象内存地址)
  • 占用空间:基本数据类型占用空间相比包装类型的要小
  • JVM存储:基本数据类型的局部变量存放在JVM栈中的局部变量表中,成员变量存放在JVM的堆中;包装类型都存放在JVM的堆中(因为都是对象)

三、包装类型的缓存机制

Java基本数据类型的包装类型大部分都提供了缓存机制来提升性能,比如:

  • ByteShortIntegerLong缓存了范围[-128, 127]的数据
  • Character缓存了范围[0,127]的数据
  • Boolean直接返回TRUEorFALSE

Integer缓存实现

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 {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;
        // ...
    }
}

Character缓存实现

public static Character valueOf(char c) {
    if (c <= 127) { // must cache
        return CharacterCache.cache[(int)c];
    }
    return new Character(c);
}

private static class CharacterCache {
    private CharacterCache() {}
    static final Character cache[] = new Character[127 + 1];
    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Character((char)i);
    }
}

Boolean缓存实现

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

超过范围的话则还是会创建新的对象,这个范围的大小是在性能和资源之间做权衡得出的。

浮点型的包装类型FloatDouble并没有实现缓存机制

Integer i1 = 50;
Integer i2 = 50;
System.out.println(i1 == i2); // 输出true

Float f1 = 50f;
Float f2 = 50f;
System.out.println(f1 == f2); // 输出false

Double d1 = 5.5;
Double d2 = 5.5;
System.out.println(d1 == d2); // 输出false

如果我们用new的方式声明对象,那么它将会创建一个新的对象,不会使用缓存

Integer i1 = 50;
Integer i2 = new Integer(50);
System.out.println(i1 == i2); // 输出false

文章作者: GaryLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 GaryLee !
  目录