1. 变量与类型
变量指的是程序运行时可变的量. 相当于开辟一块内存空间来保存一些数据.
类型则是对变量的种类进行了划分, 不同的类型的变量具有不同的特性.
1.1 整型变量(重点)
基本语法格式:
int + 变量名 = 初始值 ;
代码示例:
int a = 10 ; //定义一个值为10的整型变量
System.out.println ( a ) ;
在 Java 中, 一个 int 变量占 4 个字节. 和操作系统没有直接关系.
什么是字节?
字节是计算机中表示空间大小的基本单位.
计算机使用二进制表示数据. 我们认为 8 个二进制位(bit) 为一个字节(Byte).
即 1Byte = 8 bit 。
则 int 变量的数据范围 : -2^31 -> 2^31-1
使用以下代码查看 Java 中的整型数据范围:
System.out.println(Integer.MAX_VALUE); // int 的最大值 System.out.println(Integer.MIN_VALUE); // int 的最小值
如果运算的结果超出了 int 的最大范围, 就会出现溢出的情况。针对这种情况, 我们就需要使用更大范围的数据类型来 表示了. Java 中提供了 long 类型。
1.2 长整型变量
基本语法格式:
long + 变量名 = 初始值 ;
代码示例:
long a = 10L ; //定义一个长整型变量,初始值写作 10l 也可以(小写的 L, 不是数字1).
System.out.println ( a ) ;
在 Java 中, 一个 long 变量占 8 个字节. 表示的数据范围 -2^63 -> 2^63-1
使用以下代码查看 Java 中的整型数据范围:
System.out.println(Long.MAX_VALUE);
System.out.println(Long.MIN_VALUE) ;
// 运行结果 9223372036854775807
// -9223372036854775808
1.3 双精度浮点型变量(重点)
基本语法格式:
double + 变量名 = 初始值 ;
代码示例:
double a = 10.0 ; //定义一个双精度浮点型变量
System.out.println ( a ) ;
神奇的代码:
double num = 1.1;
System.out.println(num * num) ;
// 执行结果 1.2100000000000002
在 Java 中, 一个 double 变量占 8 个字节.
由于浮点数的内存布局和整数差别很大, 不能单纯的用 2 ^ n 的形式表示数据范围. Java 的 double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差。
1.4 单精度浮点型变量
基本格式:
float 变量名 = 初始值;
代码示例:
float num = 1.0f; // 写作 1.0F 也可以
System.out.println(num);
float 类型在 Java 中占四个字节, 同样遵守 IEEE 754 标准. 由于表示的数据精度范围较小, 一般在工程上用到浮点数都 优先考虑 double, 不太推荐使用 float.
1.5 字符类型变量
基本格式:
char 变量名 = 初始值;
代码示例:
char ch = 'A';
char ch2 = '哈';
注意事项:
1.Java 中使用 单引号 + 单个字母 的形式表示字符字面值.
2. 计算机中的字符本质上是一个整数. 在 C 语言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符. 因此一 个字符占用两个字节, 表示的字符种类更多, 包括中文. 使用一个字符表示一个汉字.
3: 执行 javac 的时候可能出现以下错误:
Test.java:错误: 未结束的字符文字 char ch = '鍛?';
^
此时我们在执行 javac 时加上 -encoding UTF-8 选项
即 javac -encoding UTF-8 Test.java
1.6 字节类型变量
基本语法格式:
byte 变量名 = 初始值;
代码示例:
byte value = 0;
System.out.println(value);
注意事项:
1. 字节类型表示的也是整数. 只占一个字节, 表示范围较小 ( -128 -> +127 )
2. 字节类型和字符类型互不相干.
1.7 短整型变量
基本语法格式:
short 变量名 = 初始值;
代码示例:
short value = 0;
System.out.println(value);
注意事项:
1. short 占用 2 个字节, 表示的数据范围是 -32768 -> +32767
2. 这个表示范围比较小, 一般不推荐使用.
1.8 布尔类型变量
基本语法格式:
boolean 变量名 = 初始值;
代码示例:
boolean value = true;
System.out.println(value);
注意事项:
1. boolean 类型的变量只有两种取值, true 表示真, false 表示假.
2. Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法.
3. boolean 类型有些 JVM 的实现是占 1 个字节, 有些是占 1 个比特位, 这个没有明确规定.
1.9 字符串类型变量(重点)
基本语法格式:
String 变量名 = "初始值";
代码示例:
String name = "zhangsan";
System.out.println(name);
注意事项:
1. Java 使用 "双引号 + 若干字符"的方式表示字符串字面值.
2. 和上面的类型不同, String 不是基本类型, 而是引用类型.
3. 字符串中的一些特定的不太方便直接表示的字符需要进行转义.
转义字符
\n 换行
\t 水平制表符
\' 单引号
\" 双引号
\\ 反斜杠
1.10 变量命名规则
硬性指标:
1. 一个变量名只能包含数字, 字母,下划线 2. 数字不能开头. 3. 变量名是大小写敏感的. 即 num 和 Num 是两个不同的变量.
注意: 虽然语法上也允许使用中文/美元符($)命名变量, 但是强烈不推荐这样做。
变量命名推荐小驼峰命名法, 当一个变量名由多个单词构成的时候, 除了第一个单词之外, 其他单词首字母都大写.
小驼峰命名示例:
int maxValue = 100;
String studentName = "张三";
1.11 常量
上面讨论的都是各种规则的变量, 每种类型的变量也对应着一种相同类型的常量.
常量指的是运行时类型不能发生改变.
常量主要有以下两种体现形式:
1.字面值常量
10 // int 字面值常量(十进制)
010 // int 字面值常量(八进制) 由数字 0 开头. 010 也就是十进制的 8
0x10 // int 字面值常量(十六进制) 由数字 0x 开头. 0x10 也就是十进制的 16
10L // long 字面值常量. 也可以写作 10l (小写的L)
1.0 // double 字面值常量. 也可以写作 1.0d 或者 1.0D
1.5e2 // double 字面值常量. 科学计数法表示. 相当于 1.5 * 10^2
1.0f // float 字面值常量, 也可以写作 1.0F
true // boolen 字面值常量, 同样的还有 false
'a' // char 字面值常量, 单引号中只能有一个字符
"abc" // String 字面值常量, 双引号中可以有多个字符.
2. final 关键字修饰的常量
final int a = 10;
a = 20; // 编译出错. 提示 无法为最终变量a分配值
常量不能在程序运行过程中发生修改.
1.12 理解类型转换
int 和 long/double 相互赋值
int a = 10;
long b = 20;
a = b; // 编译出错, 提示可能会损失精度.
b = a; // 编译通过.
int a = 10;
double b = 1.0;
a = b; // 编译出错, 提示可能会损失精度.
b = a; // 编译通过.
不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型, 反之则不行.
int 和 boolean 相互赋值
nt a = 10;
boolean b = true;
b = a; // 编译出错, 提示不兼容的类型
a = b; // 编译出错, 提示不兼容的类型
int 和 boolean 是毫不相干的两种类型, 不能相互赋值.
int字面值常量 给 byte 赋值
byte a = 100; // 编译通过
byte b = 256; // 编译报错, 提示 从int转换到byte可能会有损失
使用字面值常量赋值的时候, Java 会自动进行一些检查校验, 判定赋值是否合理(不能超过范围).
使用强制类型转换
int a = 0;
double b = 10.5;
a = (int)b;
int a = 10;
boolean b = false;
b = (boolean)a; // 编译出错, 提示不兼容的类型.
小结
1. 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型.
2. 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失.
3. 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查.
1.13 理解数值提升
int 和 long 混合运算
int a = 10;
long b = 20;
int c = a + b; // 编译出错, 提示将 long 转成 int 会丢失精度
long d = a + b; // 编译通过.
当 int 和 long 混合运算的时候, int 会提升成 long, 得到的结果仍然是 long 类型
byte 和 byte 的运算
byte a = 10;
byte b = 20;
byte c = a + b;
System.out.println(c);
// 编译报错 Test.java:5: 错误:
不兼容的类型: 从int转换到byte可能会有损失
byte c = a + b;
^
byte 和 byte 都是相同类型, 但是出现编译报错.是由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据. 为了硬件上实现方便, 诸如 byte 和 short 这种低于 4 个字节的类型, 会先提升成 int, 再参与计算.
正确的代码:
byte a = 10;
byte b = 20;
byte c = (byte)(a + b);
System.out.println(c);
int 转成 String
int num = 10;
// 方法1
String str1 = num + "";
// 方法2
String str2 = String.valueOf(num);
String 转成 int
String str = "100";
int num = Integer.parseInt(str);
2. 运算符
2.1 算术运算符(与C语言规则基本一致)
基本四则运算符 + - * / %
增量赋值运算符 += -= *= /= %=
int a = 10;
a += 1; // 等价于 a = a + 1
System.out.println(a);
自增/自减运算符 ++ --
int a = 10;
int b = ++a;
System.out.println(b);
int c = a++;
System.out.println(c);
2.2 关系运算符
关系运算符主要有六个: == != > < <= >=
int a = 10;
int b = 20;
System.out.println(a == b);
System.out.println(a != b);
System.out.println(a < b);
System.out.println(a > b);
System.out.println(a = b);
注意: 关系运算符的表达式返回值都是 boolean 类型
2.3 逻辑运算符(重点)
逻辑运算符主要有三个: && || !
注意: 逻辑运算符的操作数(操作数往往是关系运算符的结果)和返回值都是 boolean .
逻辑与 &&
规则:当两个操作数均为 true 时,结果为true;否则为假
int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b && b < c);
逻辑或 ||
规则:当两个操作数有一个为 true 时,结果为true;否则为假
int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b || b < c);
逻辑非 !
规则:操作数为 true, 结果为 false; 操作数为 false, 结果为 true
int a = 10;
int b = 20;
System.out.println( !a< b );
逻辑非 !
规则:操作数为 true, 结果为 false; 操作数为 false, 结果为 true
int a = 10;
int b = 20;
System.out.println( !a< b );
短路求值
&& 和 || 遵守短路求值的规则.
System.out.println(10 > 20 && 10 / 0 == 0); // 打印 false
System.out.println(10 < 20 || 10 / 0 == 0); // 打印 true
2.4 位运算符
Java 中对数据的操作的最小单位不是字节, 而是二进制位.
位运算符主要有四个: & | ~ ^
位操作表示 按二进制位运算. 计算机中都是使用二进制来表示数据的(01构成的序列),
按位运算就是在按照二进制位的 每一位依次进行计算.
按位与 & : 如果两个二进制位都是 1, 则结果为 1, 否则结果为 0.
int a = 10;
int b = 20;
System.out.println(a & b);
按位或 | : 如果两个二进制位都是 0, 则结果为 0, 否则结果为 1.
int a = 10;
int b = 20;
System.out.println(a | b);
按位取反 ~: 如果该位为 0 则转为 1, 如果该位为 1 则转为 0
int a = 0xf;
System.out.printf("%x\n", ~a);
按位异或 ^: 如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1.
int a = 0x1;
int b = 0x2;
System.out.printf("%x\n", a ^ b);
2.5 移位运算(了解)
移位运算符有三个: >> << >>>
都是按照二进制位来运算.
左移 <<: 最左侧位不要了, 最右侧补 0.
int a = 0x10;
System.out.printf("%x\n", a << 2);
// 运行结果(注意, 是按十六进制打印的)
40
>>: 最右侧位不要了, 最左侧补符号位 (正数补0, 负数补1)
int a = 0x10;
System.out.printf("%x\n", a >> 2);
// 运行结果(注意, 是按十六进制打印的)
4
int b = 0xffff0000;
System.out.printf("%x\n", b >> 1);
// 运行结果(注意, 是按十六进制打印的)
ffffc000
无符号右移 >>>: 最右侧位不要了, 最左侧补 0.
int a = 0xffffffff;
System.out.printf("%x\n", a >>> 2);
// 运行结果(注意, 是按十六进制打印的)
3fffffff
注意: 1. 左移 1 位, 相当于原数字 * 2. 左移 N 位, 相当于原数字 * 2 的N次方.
2. 右移 1 位, 相当于原数字 / 2. 右移 N 位, 相当于原数字 / 2 的N次方.
3. 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 的N次方的时候可以用移位运算代替.
4. 移动负数位或者移位位数过大都没有意义
2.6 条件运算符
条件运算符只有一个:
表达式1 ? 表达式2 : 表达式3
当 表达式1 的值为 true 时, 整个表达式的值为 表达式2 的值;
当表达式1 的值为 false 时, 整个表达式的值为 表达式 3 的值.
也是 Java 中唯一的一个 三目运算符, 是条件判断语句的简化写法.
// 求两个整数的最大值
int a = 10;
int b = 20;
int max = a > b ? a : b;