第二章 变量与运算符
2.1 关键字
Java语言中具有特殊意义的单词
- 用于定义数据类型的关键字
class interface enum byte short
int long float double boolean
char void
- 用于定义数据类型的关键字
true false null
- 用于控制流的关键字
if else switch case default
while do for break continue
return
- 访问修饰符
private protected public
- 用于定义类, 方法, 变量修饰符关键字
abstract final static synchronized
- 定义类之间关系的关键字
extends implements
- 实例相关的关键字
new this super instanceof
- 异常处理相关关键字
try catch finally throw throws
- 包相关
package import
- 其他
native strictfp transient volatile assert
2.2 保留字
当前尚未使用, 但以后可能作为关键字使用的单词
byValue cast future generic inner operator outer rest var goto const
2.3 标识符
2.3.1 定义
Java源代码中对各种要素命名时使用的字符序列称为标识符
2.3.2 标识符规则
- 由英文字母大小写, 数字, 下划线
(_)和美元符($) - 不可由数字开头
- 不可以使用关键字和保留字
- 不限长度
- 区别大小写
- 不能包含空格
2.4 命名规范
- 包名: 全部小写
- 类名和接口名: 每个单词的首字母大写(pascal)
- 变量和函数名: 除第一个单词外的每个单词的首字母大写(camel)
- 常量名: 所有字母都大写, 每个单词之间由下划线连接
2.5 变量
2.5.1 变量的概念
- 内存中的一个存储区域
- 这个区域有自己的名称和类型
- java中变量必须先声明, 后使用
- 该区域的数据可以在同一类型范围内不断变化
2.5.2 定义变量的格式
数据类型 变量名=初始值;
例如:
int a =100;
2.5.3 变量的作用域
一对大括号 {} 可以定义一段代码块, 在代码块内定义的变量作用域在定义之后, 代码块结束之前一直有效, 代码块可以嵌套, 内部块可以引用外部块中的变量
{
//now variable a is available
int a=100;
//some codes
{
//a new block
a=99;
}
//now variable a is 99
System.out.println("a="+a);
//some codes
}
// here variable a dose not exist
2.6 数据类型
2.6.1 分类

java的整数类型都有固定的范围和长度, 和平台无关
- 基本类型的相关信息表
| 类型 | 大小 | 默认值 | 范围 |
|---|---|---|---|
| byte | 1字节 | 0 | -128 ~ 127 |
| short | 2字节 | 0 | -2^15 ~ 2^15-1 |
| int | 4字节 | 0 | -2^31 ~ 2^31-1 |
| float | 4字节 | 0.0f | |
| long | 8字节 | 0L | -2^63 ~ 2^63-1 |
| double | 8字节 | 0.0d | |
| char | 2字节 | ‘\u0000’ | ‘\u0000’ ~ ‘\uffff’ |
| boolean | - | false | true false |
扩展阅读
boolean值只有两个值逻辑上只需要一位(1bit)即可表示, 但实际上由于处理器字长和内存对齐等因素其真实长度可能在各种jvm中并不一致
Oracle官方的 Java基本数据类型的介绍 Oracle-Java教程-数据类型
boolean类型的jvm实现 Oracle-jvms-specs 详见2.3.4节
2.6.2 类型转换
隐式类型转换
自动类型转换的实现需要同时满足两个条件:
- 两种数据类型彼此兼容
- 目标类型的取值范围大于源数据类型(低级类型数据转换成高级类型数据)。
例如: byte 类型向 short 类型转换时,由于 short 类型的取值范围较大,会自动将 byte 转换为 short 类型。
在运算过程中,由于不同的数据类型会转换成同一种数据类型,所以整型、浮点型以及字符型都可以参与混合运算。自动转换的规则是从低级类型数据转换成高级类型数据。转换规则如下:
- 数值型数据的转换:byte→short→int→long→float→double。
- 字符型转换为整型:char→int。
以上数据类型的转换遵循从左到右的转换顺序,最终转换成表达式中表示范围最大的变量的数据类型。
显式类型转换
当两种数据类型不兼容,或目标类型的取值范围小于源类型时,自动转换将无法进行,这时就需要进行强制类型转换。其语法格式如下:
(targetType)variableName
其中,targetType 为 variableName 要转换成的数据类型,而 variableName 是指要进行类型转换的变量名称,强制转换的实例如下:
int a=3;
double b=5.0;
a=(int)b;
2.7 运算符
2.7.1 算术运算符
| 运算符 | 运算 | 范例 | 结果 |
|---|---|---|---|
| + | 加 | 5+3 | 8 |
| - | 减 | 5-3 | 2 |
| * | 乘 | 5*3 | 15 |
| / | 除 | 15/3 | 5 |
| % | 模 | 13/5 | 3 |
延伸阅读 奇数性
下面的方法意图确定它唯一的参数是否时一个奇数, 这个方法能够正常运转吗
public static boolean isOdd(int i){ return i % 2 == 1; }奇数可以被定义为被 2 整除余数为 1 的整数。表达式 i % 2 计算的是 i 整除 2 时所产生的余数,因此看起来这个程序应该能够正确运转。遗憾的是,它不能; 它在四分之一的时间里返回的都是错误的答案。
为什么是四分之一, 因为int不仅包含正数还不含负数, isOdd在对所有的负奇数的判断都会失败, 任何负整数调用isOdd都会返回false, 不管该整数是奇数还是偶数
这是由于java对取余操作符的定义造成的, 该操作符被定义为对于所有的 int 数值 a 和所有的非零 int 数值 b,都满足下面的恒等式:
(a/b)*b+(a%b)==a话句话说, 用b整除a的商在乘以b加上余数的和等于a, 所以当取余结果返回一个非零的结果时, 它与左操作数具有相同的正负符号.
当i是一个负奇数时, i%2等于-1而不是1
详见java-language-specification-15.17.2. Division Operator /除法定义
java-language-specification-15.17.3. Remainder Operator %取余定义
2.7.2 赋值运算符
- 定义
赋值运算符 = 是指为变量或者常量指定数值的符号,它是双目运算符,左边的操作数必须是变量,不能是常量或者表达式
- 语法格式
变量名称=表达式内容
- 在Java中赋值还可以与一些运算符连用如下
| 运算符 | 含义 | 实例 | 结果 |
|---|---|---|---|
| += | 将该运算符左边的数值加上右边的数值, 其结果赋值给左边变量本身 | int a=5; a+=2; | a=7 |
| -= | 将该运算符左边的数值减去右边的数值, 其结果赋值给左边变量本身 | int a=5; a-=2; | a=3 |
| *= | 将该运算符左边的数值乘以右边的数值, 其结果赋值给左边变量本身 | int a=5; a*=2; | a=10 |
| /= | 将该运算符左边的数值整除右边的数值, 其结果赋值给左边变量本身 | int a=5; a/=2; | a=2 |
| %= | 将该运算符左边的数值除以右边的数值后取余,其结果赋值给左边变量本身 | int a=5; a%=2; | a=1 |
2.7.3 条件运算符
-
定义 逻辑运算符把各个运算发关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断结果是true或false。
-
逻辑运算符的用法、含义及示例
| 运算符 | 用法 | 含义 | 结合方向 | 实例 | 结果 |
|---|---|---|---|---|---|
| && | op1&&op2 | 逻辑与 | 自左到右 | 2 > 1&&3 < 4 | true |
| || | op1||op2 | 逻辑或 | 自左到右 | 2 < 1||3 > 4 | false |
| ! | !op | 逻辑非 | 自右到左 | !(2>4) | true |
- 真值表
| op1 | op2 | op1&&op2 | op1||op2 | !op1 |
|---|---|---|---|---|
| true | true | true | true | false |
| true | false | false | true | false |
| false | true | false | true | true |
| false | false | false | false | true |
2.7.4 关系运算符
关系运算符用来比较两个值的关系
| 运算符 | 含义 | 实例 | 结果 |
|---|---|---|---|
| > | 大于运算符 | 2>3 | false |
| >= | 大于或等于运算符 | 4>=2 | true |
| < | 小于运算符 | 2 < 3 | true |
| <= | 小于或等于运算符 | 4<=2 | false |
| == | 相等运算符 | 4==4 | true |
| != | 不相等运算符 | 4!=2 | true |
关系表达式通常用于Java程序的逻辑判断语句的条件表达式中。使用关系表达式要注意一下几点:
- 运算符
>=、==、!=、<=是两个字符构成的一个运算符,用空格从中分开写就会产生语法错误。例如x> =y; 是错误的,但是可以写成x>=y; 在运算符的两侧增加空格会提高可读性。同样将运算符写反,例如=>、=<、=!等形式会产生语法错误。 - 由于计算机内存放的实数与实际的实数存在着一定的误差,如果对浮点数进行
==(相等)或!=(不相等)的比较,容易产生错误结果,应该尽量避免。 - 不要将“
==”写成“=”。
扩展阅读 浮点数的相等性比较
因为浮点数的实现特性, 直接比较两个浮点数是否相等并不可靠.
在实际的应用中, 我们并不关心两个数是否完全相等, 而是在某个可以接受的误差范围内相等即可.
例如
float a=...; float b=...; if(Math.abs(a-b)<0.0001){ //equal ... }上面代码表示浮点数a和浮点数b的差的绝对值小于0.0001就认为他们相等
2.7.5 单目运算符
单目运算符的操作数只有一个
在对一个变量做加一或减一操作时, 可以使用自增运算符 ++ 或自减运算符 -- 。++或–是单目运算符,放在操作数的前面或后面都是允许的。
| 运算符 | 含义 | 实例 | 结果 |
|---|---|---|---|
| + | 正 | +3 | 3 |
| - | 负 | -3 | -3 |
| ! | 非 | !true | false |
| i++ | 将 i 的值先使用再加 1 赋值给 i 变量本身 | int i=1; int j=i++; | i=2 j=1 |
| ++i | 将 i 的值先加 1 赋值给变量 i 本身后再使用 | int i=1; int j=++i; | i=2 j=2 |
| i– | 将 i 的值先使用再减 1 赋值给变量 i 本身 | int i=1; int j=i–; | i=0 j=1 |
| –i | 将 i 的值先减 1 后赋值给变量 i 本身再使用 | int i=1; int j=–i; | i=0 j=0 |
在使用自增/自减运算时应注意下面几个问题。
- 自增/自减只能作用于变量,不允许对常量、表达式或其他类型的变量进行操作。常见的错误是试图将自增或自减运算符用于非简单变量表达式中。
- 自增/自减运算可以用于整数类型 byte、short、int、long,浮点类型 float、double,以及字符串类型 char。
在 Java 1.5 以上版本中,自增/自减运算可以用于基本类型对应的包装器类 Byte、Short、Integer、Long、Float、Double 和 Character。
- 自增/自减运算结果的类型与被运算的变量类型相同。
2.7.6 位运算符
位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算, 其操作数和运算结果都是整型值
位逻辑运算符
| 运算符 | 含义 | 实例 | 结果 | 解释 |
|---|---|---|---|---|
| & | 按位进行与运算 | 4 & 5 | 4 | 0100 & 0101 = 0100 = 4 |
| | | 按位进行或运算 | 4 | 5 | 5 | 0100 | 0101 = 0101 = 5 |
| ^ | 按位进行异或运算 | 4 ^ 5 | 1 | 0100 ^ 0101 = 0001 = 1 |
| ~ | 按位进行取反运算 | ~ 4 | -5 | ~ 0100 = 1111 1111 1111 1111 1111 1111 1111 1011 = -5 |
注意 上边运算中均为32位int型整数 因为正整数前边均为0所以省略, 负数为反码 已给出32位
位移运算符
位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数。它们都属于双目运算符。
| 运算符 | 含义 | 实例 | 结果 |
|---|---|---|---|
| » | 右移位运算符 | 8 » 1 | 4 |
| « | 左移位运算符 | 9 « 2 | 36 |
| »> | 右移补零运算符 | -1»>1 | 2147483646 |
- 右移运算符
将左操作数的二进制向右移动右操作数的值位, 移出的位丢弃, 高位补与左操作数符号位相同的数
以8位有符号整数为例
0101 1100 >> 3 = 0000 1011
1101 1100 >> 3 = 1111 1011
- 左移运算符
将左操作数的二进制向左移动右操作数的值位, 移出的位丢弃, 低位补0
0101 1100 << 3 = 1110 0000
1101 1100 << 3 = 1110 0000
- 右移补零运算符
将左操作数的二进制向右移动右操作数的值位, 移出的位丢弃, 高位补0
0101 1100 >> 3 = 0000 1011
1101 1100 >> 3 = 0001 1011
复合赋值运算符
| 运算符 | 含义 | 实例 | 结果 |
|---|---|---|---|
| &= | 按位与赋值 | num1 &= num2 | 等价于 num 1=num 1 & num2 |
| |= | 按位或赋值 | num1 |= num2 | 等价于 num 1=num 1 | num2 |
| ^= | 按位异或赋值 | num1 ^= num2 | 等价于 num 1=num 1 ^ num2 |
| ~= | 按位取反赋值 | num1 ~= num2 | 等价于 num 1=num 1 ~ num2 |
| «= | 按位左移赋值 | num1 «= num2 | 等价于 num 1=num 1 « num2 |
| »= | 按位右移赋值 | num1 »= num2 | 等价于 num 1=num 1 » num2 |
| »>= | 按位右移零填充赋值 | num1»>=num2 | 等价于 num1=num1 »> num2 |
2.7.7 类型比较运算符
instanceof 判断对象是否是某个类的对象,或实现了某个接口。
Integer a = 1;
System.out.println(a instanceof Integer);
// true
System.out.println(a instanceof Number);
// true
System.out.println(a instanceof Comparable);
// true
System.out.println(a instanceof Double);
// false
instanceof运算符只能判断对象,不能判断基础数据类型
2.7.8 运算符优先级
| 优先级 | 运算符 | 结合性 |
|---|---|---|
| 1 | () [] | 从左向右 |
| 2 | !、+、-、~、++、-- | 从右向左 |
| 3 | *、/、% | 从左向右 |
| 4 | +、- | 从左向右 |
| 5 | «、»、»> | 从左向右 |
| 6 | <、<=、>、>=、instanceof | 从左向右 |
| 7 | ==、!= | 从左向右 |
| 8 | & | 从左向右 |
| 9 | ^ | 从左向右 |
| 10 | | | 从左向右 |
| 11 | && | 从左向右 |
| 12 | || | 从左向右 |
| 13 | ?: | 从右向左 |
| 14 | =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、»>= | 从右向左 |
优先级指的是先后顺序,例如先算乘除后算加减,就意味着乘除法的优先级比加减高。
结合性指的是遇到优先级相同的运算符时,结合性指明了表达式应从左向右运算还是从右向左运算。
最后修改于 2021-10-25