任何一个需要在程序中处理的数据,无论是什么类型,都是以常量或变量的形式出现的。在程序设计中,部分常量可以不作说明而直接引用,但是变量必须在显式初始化之后才可以使用。
◆ 基本数据类型
Java 是一种强类型语言,这就意味着所有变量都必须先明确定义其数据类型才能使用。Java 语言的数据类型有两类:基本数据类型与引用类型。基本数据类型一共有八种,其中有 4 种整型、2 种浮点型、1 种用于表示 Unicode 编码的字符单元的 char 类型和 1 种用于表示真值的 boolean 类型。
数据类型 | 关键字 | 存储需求 | 取值范围 | 默认值 |
---|---|---|---|---|
布尔型 | boolean | 1 个字节(8 位) | true 、false | false |
字节型 | byte | 1 个字节(8 位) | -128 ~ 127 | (byte)0 |
短整型 | short | 2个字节(16 位) | -215 ~ 215 - 1 | (short)0 |
整型 | int | 4个字节(32 位) | -231 ~ 231 - 1 | 0 |
长整型 | long | 8 个字节(64 位) | -263 ~ 263 - 1 | 0L |
字符型 | char | 2 个字节(16 位) | ‘\u0000’ ~ ‘\uffff’ | ‘\u0000’ |
单精度浮点型 | float | 4 个字节(32 位) | 6 ~ 7 位有效位 | 0.0F |
双精度浮点型 | double | 8 个字节(64 位) | 15 位有效位 | 0.0D |
- 整型用于表示没有小数部分的数值,它允许是负值。Java 提供了 byte 、short 、int 以及 long 4 种整型,通常情况下,我们使用 int 类型,只有在统计很大数量级时才会使用 long ,而 byte 和 short 主要用于底层文件处理和控制占用存储空间的大数组等特定的应用场合
- 浮点型用于表示有小数部分的数值。两种浮点类型中,绝大部分应用程序都采用 double 类型,因为很多情况下,float 类型的精度很难满足需求。浮点数值中有正无穷大、负无穷大以及 NaN 三个比较特殊的值,另外,浮点数值不适用于无法接受舍入误差的金融计算中,因为二进制系统中无法精确地表示分数 1/10 ,比如
System.out.println(3.0 - 2.1)
,将会打印出 0.8999999999999999 ,而不是 0.9 - 字符型原本用来表示单个字符,但现在情况有所变化。有些 Unicode 字符可以用一个 char 值描述,另外一些 Unicode 字符则需要两个 char 值,因为 char 类型描述了 UTF-16 编码中的一个代码单元
- 布尔型用来判定逻辑条件,整型值和布尔值之间不能进行相互转换。也就是说,我们不可以将 boolean 类型的值进行任何算术运算,也不可以在一些需要逻辑判断的地方用 0 值代替 false ,用非 0 值代替 true
注:
- 浮点型数值在计算机内部采用科学计数法的形式,因此,float 类型的取值范围大于 int 类型,double 类型的取值范围大于 long 类型,即数据类型的取值范围与存储占用字节不一定相关
◆ 常量
Java 程序运行时,值不可修改的量称为常量,分为字面量与标识符常量两种。
1. 字面量
字面量即 Java 源程序中表示的常数值,如 8.9 、123 、 0x36 、false 、“Hello world!” 等,根据基本类型来划分,一共有 5 种。
布尔型常量(boolean)
布尔型常量值只有 true 或 false ,它们也被一些人认为是 Java 语言的关键字,不能挪作他用且必须小写。true 表示逻辑真,false 表示逻辑假。
System.out.println(true); //打印输出 true
System.out.println(false); //打印输出 false
System.out.println(0); //打印输出 0
整型常量(int 或 long)
整型常量有二进制、八进制、十进制、十六进制四种表示法。
- 十进制:十进制整数,如 123 、-64
- 二进制:以 0b 或 0B 开头的二进制整数,如 0b1001 、-0B11
- 八进制:以数字 0 开头的八进制整数,如 027 、-033
- 十六进制:以 0x 或 0X 开头的十六进制整数,如 0x13b7 、-0XAb23
注:
-
自 Java 7 开始,为增强易读性,可以为数字字面量加下划线,不会影响数值大小
-
如果要表示 long 类型的常量值,只需在整数值后加 l 或 L 作为后缀即可
-
如果要表示 byte 或 short 型的常量值,通常用强制类型转换,如 (byte)0x32b4 、(short)214
-
整型数值默认为 int 类型,如果某个常量的值超出 int 类型的取值范围,就会产生一个编译错误,为避免该错误,应该在其后加上一个后缀 l 或者 L(建议使用 L ,便于阅读),使它成为一个 long 类型常量
//十进制
System.out.println(1_2_3); //打印输出 123
System.out.println(-64); //打印输出 -64
//二进制
System.out.println(0b1_001); //打印输出 9
System.out.println(-0B11); //打印输出 -3
//八进制
System.out.println(027); //打印输出 23
System.out.println(-033); //打印输出 -27
//十六进制
System.out.println(0x13b7); //打印输出 5047
System.out.println(0XAb23); //打印输出 43811
//长整型
System.out.println(45645645454); //编译失败
System.out.println(45645645454L);//打印输出 45645645454
//强制类型转换
System.out.println((byte)56); //打印输出 56
System.out.println((byte)129); //打印输出 -127,损失了精度
浮点型常量(float 或 double)
浮点型常量有十进制小数和科学计数法这两种表现形式。
- 十进制小数形式:小数点两边的数字不能同时省略且小数点不能省略,如 3.14 、1.0
- 科学计数法形式:如 3.54×10-16 在 Java 中表示为 3.54e-16 或 3.54E-16 ,e 或 E 的前面必须有数字且 e 或 E 的后面必须是一个整数,至于更复杂的像 3.54×10-3.67 就要用到 java.lang.Math 类中的方法 pow() ,可以表示为 Math.pow(3.54,-3.67)
注:
- 浮点型数值默认为 double 类型,也可以在数值后加上 d 或 D ,它依然表示 double 类型,但如果要表示 float 类型,就需要在数值后面加上 f 或 F
//十进制小数
System.out.println(3.14); //打印输出 3.14
//科学计数法
System.out.println(3.54e-16); //打印输出 3.54E-16
字符型常量(char)
Java 中的字符采用 Unicode 字符集的编码方案,是 16 位的无符号整数,表示的字符从 0 ~ 65535 。
- 可输入字符:对于可输入字符,用单引号括起来,如 ‘q’ 、 ‘我’
- 不可输入字符:对于不可输入字符,采用转义字符表示;’\ddd’ 表示用 3 位八进制数代表的 ASCII 字符,从 ‘\000’ ~’\377’ ,可表示 256 个 ASCII 字符;’\uxxxx’ 表示用 4 位十六进制数代表 Unicode 字符,从 ‘\u0000’ ~ ‘\uffff’,可表示所有 Unicode 字符,其中的 u 可以任意连续,’\uuuuu3222’ 等价于 ‘\u3222’ ;另外还有一些比较常用的转义字符:
转义字符 | 名称 | Unicode 值 | 转义字符 | 名称 | Unicode 值 |
---|---|---|---|---|---|
\b | 退格 | \u0008 | " | 双引号 | \u0022 |
\t | 制表 | \u0009 | ’ | 单引号 | \u0027 |
\n | 换行 | \u000a | \\ | 反斜杠 | \u005c |
\r | 回车 | \u000d |
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它在 1967 年第一次发布,最后一次更新是在 1986 年,它包含了 33 个控制字符(具有某些特殊功能但是无法显示的字符)和 95 个可显示字符。
第 0~31 个字符(开头的 32 个字符)以及第 127 个字符(最后一个字符)都是不可见的(无法显示),但是它们都具有一些特殊功能,所以称为控制字符( Control Character)或者功能码(Function Code)。
注:
- Unicode 转义序列会在解析代码之前得到处理
- 注释中的 \u 也要当心,比如
//\u000a will be a newline
这行注释在编译时就会产生一个语法错误,因为 \u000a 会替换为一个换行符;类似地,//cd c:\users
也会产生一个语法错误,因为 \u 后面没有跟着 4 个十六进制数
//可输入字符
System.out.println('a'); //打印输出 a
System.out.println('我'); //打印输出 我
System.out.println(''); //编译失败
//不可输入字符
System.out.println('\"'); //打印输出 "
System.out.println('\061'); //打印输出 1
System.out.println("\u0031"); //打印输出 1
System.out.println("\uuu0031"); //打印输出 1
字符串常量(String)
Java 中字符串实际上是字符串类 java.lang.String 的一个对象,所有字符串常量值都用双引号括起来,如 “abcd” ,因为 “abcd” 是对象,所以它可以使用 String 类中的方法。
System.out.println("abcd"); //打印输出 abcd
System.out.println("abcd".length()); //打印输出 4
空常量(null)
null 可以简单看成是一个引用类型的常量值,表示不引用任何对象。在 Java 规范中,规定 null 是所谓 null类型的唯一值,且规定 null 可转换到任何引用类型。
System.out.println(null); //编译失败
2. 标识符常量
标识符常量实质上是一个变量,但它的值一旦初始化之后就不允许再发生改变,因此标识符常量要先定义后使用,通常是为了增强代码可读性而给一个常数取一个有意义的名字。标识符常量可以是任何类型,由 final 关键字声明。
final double PI = 3.1416;
System.out.println(PI); //打印输出 3.14
◆ 变量
变量是程序运行时值会发生改变的量,它对应着内存空间中的一个单元或几个单元。
1. 内涵
一个变量有三个必要的属性,即数据类型、变量名以及变量值。数据类型决定了数据存储空间的大小和能对数据执行的操作。系统会根据数据类型进行按需分配内存单元,根据数据类型判断数据的操作是否合法,变量名实质就是给它对应的内存单元取的一个有意义的名称,这样在程序中就可以按变量名来区分和使用这些内存单元了。那么变量可以用在何处?变量存储的值会一直保存着吗?这就涉及到了变量的作用域以及生存周期:
- 所谓作用域就是变量能够发挥作用的有效范围,这取决于它被声明的位置,简单来说,就是从定义它的那一行开始,到它直接所属的大括号结束为止,同一作用域的多个变量,名称不可以重复,如果在作用域之外使用变量就会造成编译失败
- 所谓生存周期就是变量能够存在的时间,这取决于变量的存储类别。如果是静态存储,变量就可以一直存在到程序运行结束,如果是动态存储则随着调用它的方法结束而消亡
/*
如果在 main 方法中出现下面这样的语句,是会编译失败的
正确的书写书写顺序应该是先定义,后使用
*/
System.out.println(x);
int x = 3;
/*
即使前面定义了相应的变量,但如果不属于同一作用域,也会编译失败
*/
{
int y = 4;
System.out.println(x); //成功打印
}
System.out.println(y); //编译失败
2. 声明
每个变量都必须有一个类型,在声明变量时,变量的类型位于变量名之前,每个声明以分号结束,也可以在一行中声明多个变量,不过,一般不提倡这种风格。逐一声明每一个变量可以提高程序的可读性。有时候很难给变量取一个合适的名字,所以我们可以直接使用类型名或者在类型名前加 a 作为变量名。
//声明单个变量
int aInt;
double aDouble;
//声明多个同类型变量
int x, y, z;
3. 初始化
一个变量声明之后,必须用赋值语句对变量进行显式初始化,千万不要使用未初始化的变量如果在使用之前没有给变量赋初值:
-
当该变量是静态存储类型的变量时,系统编译时会自动赋默认初值
-
当该变量是动态存储类型的变量时,是会编译失败的
想要对一个已经声明过的变量进行初始化,就需要将变量名放在等号(=)左侧,相应取值的 Java 表达式放在等号的右侧;也可以将变量的声明和初始化放在同一行中,而且变量的声明可以放在代码中的任何位置,但我们应该尽可能的在靠近变量第一次使用的地方进行变量的声明。
//声明单个变量然后进行初始化
int aInt;
aInt = 3;
//声明多个变量然后进行初始化
int m, n;
m = 4;
n = 5;
//声明单个变量并进行初始化
double aDouble = 3.14;
//声明多个变量并对部分变量进行初始化
int x, y = 1, z;
double a = 2.3, b;
//声明多个变量并进行初始化
int p = 4, q=6;