Java共有8中基本数据类型:byte、boolean、char、short、int、float、long、double。
对应的包装类分别为:Byte、Boolean、Character、Short、Integer,Float,Long,Double

1. byte、Byte

byte表示一个字节,它的取值范围时-128~127。

public static final byte   MIN_VALUE = -128;

    public static final byte   MAX_VALUE = 127;

思考:为什么byte取值范围时-128~127呢?

首先,复习以下原码、反码、补码的概念。

  • 原码: 最高位为符号位(0为正,1为负)表示的二进制表示形式。
  • 反码: 正数的反码为其本身,负数的反码符号位保持不变,其余位取反。
  • 补码: 正数的补码为其本身,负数的补码为其反码+1。
  • 补码转原码: 正数的补码就是原码,负数的补码-1后,符号位不变,其余位取反后得原码

为什么要有原码、反码和补码呢?因为计算机电路中只有加法器,而没有减法器,所以只能通过转换为补码的形式来计算。计算机中的有符号数都是以补码表示的。

举例:-3+1 = -2

十进制

原码

反码

补码

-3

10000011

11111100

11111101

1

00000011

00000011

00000011

补码相加:11111101+00000011=11111110

再转换为原码:保持符号位不变,补码j=11111110,取反得1000

过程

结果

补码

11111110

补码-1

11111101

取反

10000010

十进制

-2

再回过头看byte的取值范围。

  • 正数: 00000000 ~ 01111111(补码)。
  • 负数: 10000000 ~ 11111111(补码)
    以上是计算机里的补码表示形式,把他们转为原码:

补码

原码

十进制

00000000

00000000

0

01111111

01111111

127

10000000

11111111

-128

11111111

10000001

-1

换算成十进制后范围便为-128~127。

总结:byte的范围是-128 ~ 127是因为,8位有符号整数的表示范围为-127 ~ 128。

2. boolean、Boolean

boolean即布尔值,取值为true或false。

💡 注意: boolean和Boolean在使用lombok生成getter/setter时有所不同。请看如下例子:

public class BooleanGetterSetter { @Data public static class Man { private String name; private boolean isMan; private boolean boy; private Boolean isGirl; } public static void main(String[] args) { Man man = new Man(); //对于基本类型boolean定义的变量,生成setter时,如果是is开头的,则默认省略is man.setMan(true); man.setBoy(true); //对于包装类型Boolean定义的变量,生成setter时,则按照直接加set前缀且首字母变为大写的方式生成 man.setIsGirl(false); //同样的,对于生成的getter也是如此 boolean giril = man.getIsGirl(); boolean isMan = man.isMan(); boolean isBoy = man.isBoy(); } }

3. char、Character

char代表一个Unicdoe字符,2个字节,16位。

💡 注意: char只能表示范围在2个字节(即一个代码单元)内的字符,超过2个字节的无法表示,如这个笑脸表情😀,char c = '😀'则会编译不通过,因为它超过了char的范围,此时只能用String来存储,我们可以通过new String(“😀”)的方式,在idea中断点看到它真实的值:

java private boolean类型赋值 java数据类型boolean_Boo


实际上它是由两个Unicdoe编码组成的:

\uD83D

\uDE00

。我们可以通过String来还原这个笑脸:

char[] smail = new char[]{'\uD83D','\uDE00'}; System.out.println(String.valueOf(smail)); //输出😀

Character是char的包装类,一般开发中使用场景并不多,最常用的还是String,偶尔会使用到它的大小写判断和转换:

Character.isLowerCase();
Character.isUpperCase();
Character.toLowerCase();
Character.toUpperCase();

4. short、Short

short是短整型,16位,2个字节,和char长度相同,不过short是有符号整数,所以它的范围是-32768~32767,同样的,它的范围计算方式和byte的计算方式一致。short的使用场景也不是很多,在确认数据不会超出short范围后,可以使用short来节省空间。

5. int、Integer

int是最常用的整型,32位,4字节,取值范围位-2147483648 ~ 2147483647,即-231~-231-1。

@Native public static final int   MIN_VALUE = 0x80000000;

    @Native public static final int   MAX_VALUE = 0x7fffffff;

💡注意:Integer默认缓存了-128~127的值,并且最大值是可以通过参数-Djava.lang.Integer.IntegerCache.high=<sizie>配置的

// high value may be configured by property
int h = 127;
String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

因此如果Integer的值在-128~127之间时,如下输出都是true:

public class IntAndInteger {
    public static void main(String[] args) {
        //缓存范围内,可以使用==比较,超出范围的需要用equals
        Integer a = 127;
        Integer b = 127;
        Integer c = 128;
        Integer d = 128;
        System.out.println(a == b);
        //输出:true
        System.out.println(c == d);
        //输出:false
        System.out.println(c.equals(d));
        //输出:true
    }
}

6. float、Float

float表示单精度浮点型,32位,4字节。其中,1为符号位,8位指数位(无符号),23位尾数位,十进制取值范围为:1.4E-45 ~ 3.4028235E38。其二进制的表示形式以及计算方式,可参考《计算机组成原理》一书。

在Java开发中,我们需要注意,float的精度有限,有些数字不能精确表示,因此如果需要精确计算(如金额)的时候,float并不合适。

Float是float的包装类,需要注意的是Float虽然提供了compare和equals方法,但是需要注意要比较的数是否在精度范围内,否则会发生数值不相等compare却为0或equals为true的情况。另外,应该静止使用浮点数来作为循环变量。

💡 提示:对于高精度要求的数值计算,需要使用BigDecimal

7. long、Long

long表示长整型,64位,8字节。
Long是long的包装类,和Integer类型一样,它也缓存了-128~127。

//最小值 -2^63
    @Native public static final long MIN_VALUE = 0x8000000000000000L;
	//最大值 2^63-1
    @Native public static final long MAX_VALUE = 0x7fffffffffffffffL;

8. double、Double

double表示双精度浮点型,64位,8字节。其中,1为符号位,11位指数位(无符号),52位尾数位,十进制取值范围为:4.9E-324 ~ 1.7976931348623157E308,除范围和精度外和float基本相同。

9. 特殊类型void

void是一个特殊的类型,有人把它归到Java基本数据类型中,是因为可以通过Class.getPrimitiveClass("void")获取对应的原生类型,所以如此看来Java的基本数据类型就有9种,实际上,这仅仅是一个分类问题,不同的分类规则,结果也不同。
值得注意的是,void有个对应的类型Void,可以把它看做是void的包装类,Void的作用主要作用有以下2个:

  • 泛型占位
    当我们定义了泛型时,如果没有写泛型参数,idea等开发工具会给出提醒,建议写上泛型类型,但实际上却是不需要固定的泛型类型,这时候据可以写上Void来消除警告,例如ResponseData<Void>
  • 反射获取void方法
Method[] methods = String.class.getMethods();
for (Method method : methods) {
    if(method.getGenericReturnType().equals(Void.TYPE)){
        System.out.println(method.getName());
    }
}
//输出:
//getBytes
//getChars
//wait
//wait
//wait
//notify
//notifyAll