目录
一. 前言
二. 基本数据类型
2.1. char(字符型)
2.2. byte(字节型)
2.3. short(短整型)
2.4. int(整型)
2.5. long(长整型)
2.6. float(单精度浮点型)
2.7. double(双精度浮点型)
2.8. boolean(布尔型)
三. 类型转换
3.1. 自动转换
3.2. 强制转换
3.3. 类型自动提升
3.4. 自动装箱和自动拆箱
四. 实例
五. 引用类型
六. Java 常量
一. 前言
Java 是一门强类型的编程语言,所有的变量必须显式声明数据类型。Java 中定义了多种数据类型,根据数据的特点,数据类型分为两大类:基本数据类型和引用数据类型(简称引用类型)。
Java 中数据类型的分类如下图所示:
二. 基本数据类型
变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间。内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据。因此,通过定义不同类型的变量,可以在内存中储存整数、小数或者字符。
基本数据类型包括 4 类 8 种,4 类分别是整数类型、浮点类型、字符类型和布尔类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
数据类型 | 占用字节 | 默认值 | 包装类 |
---|---|---|---|
char(字符型) | 1 | \u0000 | Character |
byte(字节型) | 1 | 0 | Byte |
short(短整型) | 2 | 0 | Short |
int(整型) | 4 | 0 | Integer |
long(长整型) | 8 | 0L | Long |
float (单精度浮点型) | 4 | 0.0f | Float |
double (双精度浮点型) | 8 | 0.0d | Double |
boolean(布尔型) | 1 | false | Boolean |
注意:在 Java 中,整形和浮点型都是有符号的。
2.1. char(字符型)
- char 类型是一个单一的16位 Unicode 字符;
- 最小值是 ’\u0000’(即为 0);
- 最大值是 ’\uffff’(即为65,535);
- char 数据类型可以储存任何字符;
- 例子:char letter = ‘A’。
2.2. byte(字节型)
- byte 数据类型是8位、有符号的,以二进制补码表示的整数;
- 最小值是 -128(-);
- 最大值是 127(-1);
- 默认值是 0;
- byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
- 例子:byte a = 100,byte b = -50。
2.3. short(短整型)
- short 数据类型是16位、有符号的以二进制补码表示的整数
- 最小值是 -32768(-);
- 最大值是 32767( - 1);
- short 数据类型也可以像 byte 那样节省空间。一个 short 变量是 int 型变量所占空间的二分之一;
- 默认值是 0;
- 例子:short s = 1000,short r = -20000。
2.4. int(整型)
- int 数据类型是 32 位、有符号的以二进制补码表示的整数;
- 最小值是 -2,147,483,648(-);
- 最大值是 2,147,483,647( - 1);
- 一般地整型变量默认为 int 类型;
- 默认值是 0;
- 例子:int a = 100000, int b = -200000。
2.5. long(长整型)
- long 数据类型是 64 位、有符号的以二进制补码表示的整数;
- 最小值是 -9,223,372,036,854,775,808(-);
- 最大值是 9,223,372,036,854,775,807( -1);
- 这种类型主要使用在需要比较大整数的系统上;
- 默认值是 0L;
- 例子:long a = 100000L,long b = -200000L。
2.6. float(单精度浮点型)
- float 数据类型是单精度、32 位、符合 IEEE 754 标准的浮点数;
- float 在储存大型浮点数组的时候可节省内存空间;
- 默认值是 0.0f;
- 浮点数不能用来表示精确的值,如货币;
- 例子:float f1 = 234.5f。
2.7. double(双精度浮点型)
- double 数据类型是双精度、64位、符合 IEEE 754 标准的浮点数;
- 浮点数的默认类型为 double 类型;
- double 类型同样不能表示精确的值,如货币;
- 默认值是 0.0d;
- 例子:double d1 = 123.4。
2.8. boolean(布尔型)
- boolean 数据类型表示一位的信息;
- 只有两个取值:true 和 false;
- 这种类型只作为一种标志来记录 true / false 情况;
- 默认值是 false;
- 例子:boolean one = true。
三. 类型转换
在 Java 中,将一种类型的值赋值给另一种类型是很常见的。boolean 类型与其他7种类型的数据都不能进行转换,char 类型不支持自动转换成它,只支持强制转换,除了这两种类型有些特殊以外,其他 6 种数据类型,它们之间都可以进行相互转换,只是可能会存在精度损失。
将 6 种数据类型按取值范围的大小顺序排列一下:
double > float > long > int > short > byte
取值范围从小转换到大,是可以直接转换的,而从大转成小,或转成 char 类型,则必须使用强制转换。
3.1. 自动转换
自动转换时会进行扩宽(widening conversion)。因为较大的类型(如 int)要保存较小的类型(如 byte),取值范围是足够的,不需要强制转换。
在自动类型转化中,除了以下几种情况可能会导致精度损失以外,其他类型的自动转换不会出现精度损失:
- int --> float
- long --> float
- long --> double
- float --> double
除了可能的精度损失外,自动转换不会出现任何运行时(run-time)异常。
3.2. 强制转换
如果要把大的转成小的,或者在 short 与 char 之间进行转换,就必须强制转换。这也被称作缩小转换(narrowing conversion),因为必须显式地使数值更小以适应目标类型。
强制转换的格式和实例如下:
(target-type) value;// 实例
long lo = 99;
int i = (int) lo;
严格地说,byte 转为 char 不属于(narrowing conversion),因为从 byte 到 char 的过程其实是 byte --> int --> char,所以 widening 和 narrowing 都有。
强制转换可能会损失精度,主要有两种场景:
- 整数类型之间相互转换,如果整数超出目标类型范围,会对目标类型的范围取余数。
- 从浮点类型转成整数类型,会发生截尾(truncation),也就是把小数的部分去掉,只留下整数部分。此时如果整数超出目标类型范围,一样将对目标类型的范围取余数。
3.3. 类型自动提升
在表达式计算过程中会发生类型转换,这些类型转换就是类型提升,类型提升规则如下:
- 所有 byte / short / char 的表达式都会被提升为 int;
- 除以上类型,其他类型在表达式中,都会被提升为取值范围大的那个类型,例如有一个操作数为 double,整个表达式都会被提升为 double。
3.4. 自动装箱和自动拆箱
Java 是面向对象语言,其概念为一切皆为对象,但基本数据类型是个例外。基本数据类型大多是面向机器底层的类型,它是 “值” 而不是一个对象,对于声明在方法中的基本类型变量,它存放于“栈”中而不是存放于“堆”中。这有很多好处,例如不需要和对象一样需要在堆中分配内存,然后搞个引用指向它。不需要 GC,因为是直接在栈上分配空间,方法运行结束就出栈回收掉了。可以放心的使用最基本的运算符进行比较和计算等等。
没有什么是完美无缺的,数据类型也有缺点,例如会自动设置默认值(这是双刃剑,一些场景下会增加额外的处理逻辑),不支持泛型等。
Java 希望使用一切皆为对象的理念来统一语言设计,但基本类型确实有很多优点和使用场景,鱼和熊掌我就要兼得之!所以它为每一个基本类型都提供了相应的包装类,封装了很多实用的方法,最重要的是,提供了自动装箱和自动拆箱的语法糖,让开发者可以无感知的在包装类型和基础类型之间来回切换。
四. 实例
对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。请看下面的例子:
public class PrimitiveTypeTest {public static void main(String[] args) {// byteSystem.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);System.out.println("包装类:java.lang.Byte");System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);System.out.println();// shortSystem.out.println("基本类型:short 二进制位数:" + Short.SIZE);System.out.println("包装类:java.lang.Short");System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE);System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE);System.out.println();// intSystem.out.println("基本类型:int 二进制位数:" + Integer.SIZE);System.out.println("包装类:java.lang.Integer");System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE);System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE);System.out.println();// longSystem.out.println("基本类型:long 二进制位数:" + Long.SIZE);System.out.println("包装类:java.lang.Long");System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE);System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE);System.out.println();// floatSystem.out.println("基本类型:float 二进制位数:" + Float.SIZE);System.out.println("包装类:java.lang.Float");System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE);System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE);System.out.println();// doubleSystem.out.println("基本类型:double 二进制位数:" + Double.SIZE);System.out.println("包装类:java.lang.Double");System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE);System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE);System.out.println();// charSystem.out.println("基本类型:char 二进制位数:" + Character.SIZE);System.out.println("包装类:java.lang.Character");// 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台System.out.println("最小值:Character.MIN_VALUE="+ (int) Character.MIN_VALUE);// 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台System.out.println("最大值:Character.MAX_VALUE="+ (int) Character.MAX_VALUE);}
}
编译以上代码输出结果如下所示:
基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127
基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535
Float 和 Double 的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示 E 之前的数字要乘以 10 的“数字”次幂。比如 3.14E3 就是 3.14×1000=3140,3.14E-3 就是3.14/1000=0.00314。
实际上,JAVA 中还存在另外一种基本类型 void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。
五. 引用类型
- 引用类型变量由类的构造函数创建,可以使用它们访问所引用的对象。这些变量在声明时被指定为一个特定的类型,比如 Employee、Pubby 等。变量一旦声明后,类型就不能被改变了。
- 对象、数组都是引用数据类型。
- 所有引用类型的默认值都是 null。
- 一个引用变量可以用来引用与任何与之兼容的类型。
- 例子:Animal animal = new Animal(“giraffe”)。
六. Java 常量
常量就是一个固定值。它们不需要计算,直接代表相应的值。
常量指不能改变的量。 在 Java 中用 final 标志,声明方式和变量类似:
final double PI = 3.1415927;
虽然常量名也可以用小写,但为了便于识别,通常使用大写字母表示常量。
字面量可以赋给任何内置类型的变量。例如:
byte a = 68;
char a = 'A'
byte、int、long、和 short 都可以用十进制、16进制以及8进制的方式来表示。
当使用常量的时候,前缀0表明是8进制,而前缀 0x 代表16进制。例如:
int decimal = 100;
int octal = 0144;
int hexa = 0x64;
和其他语言一样,Java 的字符串常量也是包含在两个引号之间的字符序列。下面是字符串型字面量的例子:
"Hello World"
"two\nlines"
"\"This is in quotes\""
字符串常量和字符常量都可以包含任何 Unicode 字符。例如:
char a = '\u0001';
String a = "\u0001";
Java 语言支持一些特殊的转义字符序列:
符号 | 字符含义 |
---|---|
\n | 换行 (0x0a) |
\r | 回车 (0x0d) |
\f | 换页符(0x0c) |
\b | 退格 (0x08) |
\0 | 空字符(0x0) |
\s | 字符串 |
\t | 制表符 |
\" | 双引号 |
\' | 单引号 |
\\ | 反斜杠 |
\ddd | 八进制字符 (ddd) |
\uxxxx | 16进制Unicode字符 (xxxx) |