今天的博客主题
Java编程基础 ——》Java操作符
操作符
Java的操作符作用于操作数上,用来生成一个新的数值。
有些操作符会改变自身的数值,这被称为“副作用”。
Java中的操作符有以下几种
- 分隔符
- 算术运算符
- 关系运算符
- 逻辑运算符
- 赋值运算符
- 三目运算符
- 字符串拼接符
- 位运算符
表达式
表达式,是由数字、算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。
约束变量在表达式中已被指定数值,而自由变量则可以在表达式之外另行指定数值。
优先级
当一个表达式中存在多个操作符时,操作的优先级就决定了各部分的计算顺序。
Java对计算顺序做了特别的规定。其中最简单的就是先乘除后加减
运算符优先级的一个顺序大致是
分隔符 ---》 算术 --》 关系 --》 逻辑 --》 三目 --》 赋值
int i = (1 > (2 + 3) - 4 / 1) && 5 < 6 ? 7 : 8;
分隔符
空格、逗号、分号以及行结束符都被称为分隔符,规定任意两个相邻标识符、数字、保留字或语句之间必须至少有一个分隔符,以便程序编译时能够识别。
分号: ; 用来终止一个语句。
逗号: , 在变量声明中,区分变量说明的各个变量。在for控制语句中,用来将圆括号内的语句连接起来。 原点: . 用来将软件包的名字与它的子包或类分隔。也用来将引用变量与变量或方法分隔。
小括号:() 在定义和调用方法时用来容纳参数表。在控制语句或强制类型转换组成的表达式中用来表示执行或计算的优先权。
中括号:[] 用来声明数组的类型,也用来表示撤消对数组值的引用。
大括号:{} 来包括自动初始化的数组的值,也用来定义程序块、类、方法以及局部范围。
算术运算符
Java的基本算术操作符与其他大多数语言是相同的。
其中有:加号(+)减号(-)乘号(*)除号(/)取模(%)
特殊的:自增(++)自减(--)
加减乘除
就不在详细解释了,二年级的同学都知道。
取模,取余:
取模用于计算机术语中。取余则多是数学的概念。
未理解。待补充。
自增,自减
全称是自动递增和自动递减,是一个比较快捷的运算。
自增(++):自动增加一个单位
自减(--):自动减少一个单位
两种使用方式:前缀使用,后缀使用
int a = 1; // 整数类型值
++a; // 等价于 int a = a + 1;
--a; // 等价于 int a = a - 1;
a++; // 等价于 int a = a; a = a + 1;
a--; // 等价于 int a = a; a = a - 1;
自增(++)在前的时,先自增1,再赋值,在后的时候,先赋值,再自增1
自减(--) 在前的时,先自减1,再赋值,在后的时候,先赋值,再自减1
注意:
1)除法会直接去结果的小数位,不会四舍五入的圆整结果
2)除法的被除数不可为0
关系运算符
关系操作符生成的结果是一个boolean类型的。
计算的是操作数的值之间的关系。
结果是真实的,关系表达式会生成真(true),不真实则是假(false)
关系操作符有:大于(>)小于(<)大于等于(>=)小于等于(<=)不等于(!=)等于(==)
等等于和不等于适用于所有基本数据类型。其他的则不适用于boolean类型的。
因为boolean类型结果只由true和false,大于小于对于它们没有实际的意义。
等于,不等于
大于,小于,大于等于,小于等于这些就不详细解释了。无非是谁大于谁,谁小于谁。
重点说下这个等于,不等于。
// == != 作用于基本数据类型是比较值
int a = 1;
int b = 1;
a == b; // true
a != b; // false
// == != 作用于引用数据类型是比较引用
Integer a1 = new Integer(1);
Integer b1 = new Integer(1);
a1 == b1; // false
a1 != b1; // true
尽管a1 和 b1内容是相同的,但是对象的引用地址却是不同的。
不要搞混了。
那怎么比较对象的实际内容是否相同呢?
只需要所有的引用数据类型来重写equals()方法即可。
Java的大多类库都重写了equals方法,用来比较对象的内容,而非比较对象的引用。
a1.equals(b1); // true
注意:
1)== 和 != 在基本数据类型上比较的是内容,在引用数据类型上比较的是引用。
如果想比较引用数据类型的内容,先重写equals()方法,在用equals比较。
2)关系运算符返回值类型是boolean类型。
逻辑运算符
逻辑操作符只可应用于boolean类型的结果值上。
而逻辑运算符的结果也是boolean类型。
逻辑操作符:与(&&)或(||)非(!)
// && (并且)符号左右表达式的结果必须都为真,结果才为真,否则就是false
// 这句代码的读法:2大于1 并且 1小于2
(2 > 1) && (1 < 2); // true 2大于1是true 并且 1小于2是true 结果就为true
// || (或者)符号左右表达式的结果只要一个为真,结果就是真
// 这句代码的读法:2大于2 或者 1小于2
(2 > 2) || (1 < 2); // true 2大于2是false 或者 1小于2是true 结果就是true
// ! (非) 取表达式结果的相反值。表达式前面加!那结果就变了
// 这句代码的读法:2大于2 非 并且 1小于2
!(2 > 2) && (1 < 2); // true 2大于2是false 表达式加! 结果就变true 并且 1小于2是true 结果就是true
短路
在使用逻辑操作符时,会遇到一种短路现象。
就是一旦能够明确无误的确定整个表达式的值,就不在计算后面的部分了。
(1 + 1) > 2 && (3 + 4) < (5 + 6) && 8 > 7; // false
在这段表达式中,找到操作符运算的优先级顺序后,依次执行。
当计算完 (1 + 1) > 2 发现结果为 false,那后面的一些计算,也就没必要继续执行计算下去了。
算下去也是浪费时间,短路就源于此。
表达式有一部分都都不计算,这也使得程序获得了潜在的性能提升。
连接符
连接符(+)这个符号和运算符里的加号一样。
但它有一项特殊的用途:连接不同的字符串。
当这个符号前后有一个是字符串类型的字符时,就做拼接字符串。
符号前后都是数字类型时候,就做加法运算。
String a = "1";
int b = 2;
a + b; // 结果:12 前后一个是字符串就拼接
int c = 1;
b + c; // 结果:3 前后都是数字,就做加法运算
赋值运算符
赋值符(=)就是把右边的值,复制到左边。
右边的值可以是任何常数,变量或者表达式(能生成一个值就行)。
但是左边必须是一个明确的,已命名的变量。也就是说必须有一个物理空间可以存储右边的值。
// 任何常数
int a = 1;
// 任何变量
int b = a;
// 任何表达式
int c = (a + b) * 3;
赋值运算符:加等(+=)减等(-=)乘等(*=)除等(/=) 模等于(%=)
这些就是先做一个简单运算符运算,在把运算结果进行赋值
// += 加等于
int a = 1;
int b = 2;
// 下面这句代码等价于:b = b + a;
b += a; // 这时候b不在是2,而是变成了3
只不过是将b的值从新计算并赋值,在写法上简洁些,别的没啥用
别的赋值运算符就不介绍了,都一样,先运算在赋值。
三目运算符
三目运算符也被称为:三元运算符,条件操作符
因为它有三个操作数,显得比较特别。不过也属于操作符的一种。
它的表达式形式是这样的
boolean-exp ? v1 : v2
boolean-exp是一个boolean类型的表达式。
结果为true,那就取v1,否则那就取v2
// 这句代码就是:如果1+1大于1 那a的值就是2,否则就是0。
int a = (1 + 1) > 1 ? 2 : 0; // a=0
这个有点像流程控制语句里的 if...else...,但又完全不同,因为三目运算符会产生一个值出来。
这样写,是比较简洁的。
虽然这样会体现出高效的编程,但要是频繁的使用,还需谨慎,因为很容易产生可读性极差的代码。
位运算符
位操作符是用来对二进制位进行操作的。
位运算符的目的是为了节约内存开销和加快计算的效率。
不会过多的使用到位操作符,但是见到了不能不认识。
位操作符分为:按位操作和移位操作
按位操作符有:位与(&)、位或(|)、位非(~)、位异或(^)
// & (位与) 两个数的二进制,相同位数是1,则该位是1,否则是0
5&4
5的二进制 0000 0000 0000 0101
4的二进制 0000 0000 0000 0100
5&4的结果 0000 0000 0000 0100 转为十进制就是4
// | (位或) 两个数的二进制,相同位数有一个1,则该位是1,否则是0
// ^ (位异或) 个数的二进制,相同位数只有一个是1,则该位是1,否则是0
// ~ (位非) 按位“非”操作符,也称为取反操作符。若输入0,则输出1,若输入1,则输出0。
移位操作符有:右移位(>>)、左移位(<<)、0填充的右移(>>>)
移位操作符只可用来处理整数类型。
// >> 右移位:按照操作符右侧指定的位数将操作符左边的操作数向右移
5>>2 等于 1
5的二进制 0000 0000 0000 0101 根据符号右指定的位数移动两位
则变成 0000 0000 0000 0001 转为十进制就是1
// << 左移位:按照操作符右侧指定的位数将操作符左边的操作数向左移(在低位补0)
5<<2 等于 20
5的二进制 0000 0000 0000 0101 根据符号右指定的位数移动两位
则变成 0000 0000 0001 0100 转为十进制就是20
有符号右移位操作符使用符号扩展。若符号位正,则在高位插入0。若符号位负,则在高位插入1。
Java增加了一种无符号右移位操作符(>>>),无论正负,都在高位插入0。
5>>>2 等于 1 5的二进制 0000 0000 0000 0101 右移两位 0000 0000 0000 0001 -5>>>2 等于 1073741822 -5的二进制是 1111 1111 1111 1011 右移两位 0011 1111 1111 1110
移位与等号组合使用(<<=,>>=,>>>=)
操作符左边的值会移动由右边的值指定的位数,再将得到的结果赋值给左边的变量。
但是在进行无符号右移位结合赋值操作时,可能会遇到一个问题,就是在对byte或short值进行移位运算,得到的可能不是正确的结果。它们会被先转成int类型,再进行右移操作,然后被截断,赋值给原来的类型,这种情况下可能得到-1的结果。
short s = -1;
s>>>=10
转换为int二进制 1111 1111 1111 1111 1111 1111 1111 1111
右移10位 0000 0000 0011 1111 1111 1111 1111 1111
正确十进制结果为4194303
截断16位赋值short 1111 1111 1111 1111
实际十进制结果为-1
拓展
一元加号、一元减号
一元运算符,二元运算符,三元运算符