计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量。
我们可以把运算符分成以下几组:
- 算术运算符
- 位运算符
- 关系运算符
- 逻辑运算符
- 赋值运算符
- Instanceof运算符
算术运算符
运算符顾明思义是一种符号,它是连接一个以上的操作符,实现某种功能的运算符。
我们就先来认识一下算数运算符把!
算术运算符用在数学表达式中,主要实现的是算数运算,如我们常见的加减乘除等。
表格中的实例假设整数变量a的值为7,变量b的值为3:
算术运算符 | 描述 | 类型 | 例子 |
---|---|---|---|
+ | 加法 - 相加运算符两侧的值 | 双目运算符 | a+b等于10 |
- | 减法 - 左操作数减去右操作数 | 双目运算符 | a - b 等于4 |
* | 乘法 - 相乘操作符两侧的值 | 双目运算符 | a * b 等于 21 |
/ | 除法 - 左操作数除以右操作数 | 双目运算符 | a / b 等于 2 |
% | 取余 - 左操作数初右操作数的余数 | 双目运算符 | a % b 等于 1 |
++ | 自增 - 操作数的值加1 | 单目运算符 | ++a(或a++) 等于 8 |
-- | 自减 - 操作数的值减少1 | 单目运算符 | --a(或a--) 等于 6 |
其中,自增(++)和自减(--)运算符有两种写法:前缀(++i, --i)和后缀(i++, i--)。
- 前缀自增自减法(++i, --i):先进行自增或自减运算,在进行表达式运算。
- 后缀自增自减法(i++, i--):先进行表达式运算,再进行自增或自减运算。
我们可以编写一下代码来进行直观的感受:
public class Test {
public static void main(String args[]) {
int a = 5;
int b = 3;
int c = 3;
int d = 3;
System.out.println("a + b = " + (a + b));
System.out.println("a - b = " + (a - b));
System.out.println("a * b = " + (a * b));
System.out.println("a / b = " + (a / b));
System.out.println("a % b = " + (a % b));
System.out.println("a++ = " + (a++));
System.out.println("++a = " + (++a));
System.out.println("b-- = " + (b--));
System.out.println("--b = " + (--b));
System.out.println("c++ = " + (c++));
System.out.println("++d = " + (++d));
}
}
运行结果:
a + b = 8
a - b = 2
a * b = 15
b / a = 1
b % a = 2
a++ = 5
++a = 7
b-- = 3
--b = 1
c++ = 3
++d = 4
大家可以发现++在变量的左边和右边,赋值得到的结果是不一样的,自减也是同样。
测试题:
public static void main(String[] args) {
int a = 10;
int b = 10;
int c = 10;
a = b++;
c = --a;
b = a--;
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
public static void main(String[] args) {
int a = 1;
a = a++;
System.out.println(a);
int b = a++ * ++a;
System.out.println(b);
}
位运算符
Java定义了位运算符,应用于整数类型(int)、长整型(long)、短整形(short)、字符型(char)和字节型(byte)等类型。位运算时先转换为二进制,在按位运算。
表格中的例子,变量a的值为60(00111100),变量b的值为13(00001101)
位运算符 | 描述 | 例子 |
---|---|---|
& | 按位与 - 如果相对应位都是1,则结果为1,否则为0 | (a&b),得到12,即0000 1100 |
丨 | 按位或 - 如果相对应位都是0,则结果为0,否则为1 | (a丨b)得到61,即0011 1101 |
^ | 按位异或 - 如果相对应位值相同,则结果为0,否则为1 | (a^b)得到49,即0011 0001 |
~ | 按位补 - 翻转操作数的每一位,即0变为1,1变为0 | (~a)得到-61,即1100 0011 |
<< | 按位左移 - 左操作数按位左移右操作数指定的位数 | a<<2得到240,即1111 0000 |
>> | 按位右移 - 左操作数按位右移右操作数指定的位数 | a>>2得到15,即1111 |
>>> | 按位右移补零 - 左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充 | a>>>2得到15,即00001111 |
接下来输入一下代码,进行验证:
public class Test {
public static void main(String args[]) {
int a = 60;
int b = 13;
System.out.println("a & b = " + (a & b));
System.out.println("a | b = " + (a | b));
System.out.println("a ^ b = " + (a ^ b));
System.out.println("~a = " + (~a));
System.out.println("a << 2 = " + (a << 2));
System.out.println("a >> 2 = " + (a >> 2));
System.out.println("a >>> 2 = " + (a >>> 2));
}
}
运算结果:
a & b = 12
a | b = 51
a ^ b = 61
a << 2 = 240
a >> 2 = 15
a >>> 2 = 15
注意事项:一个数异或同一个数两次,结果还是本身
测试题:不借助第三个变量的前提下交换两个整数变量的值
public class day2 {
public static void main(String[] args) {
int a = 3;
int b = 7;
System.out.println("交换前的值为:a=" + a + ", b=" + b);
a = a + b;
b = a - b;
a = a - b;
System.out.println("交换前的值为:a=" + a + ", b=" + b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("交换前的值为:a=" + a + ", b=" + b);
}
}
逻辑运算符
逻辑运算符是通过运算符将操作数或等式进行逻辑判断的语句。
表格中的例子中,假设布尔变量a为真,变量b为假:
逻辑运算符 | 描述 | 类型 | 例子 |
---|---|---|---|
&& | 与 - 当且仅当两个操作数都为真,条件才为真 | 双目运算符 | (a&&b)为假 |
丨丨 | 或 - 两个操作数任何一个为真,条件为真 | 双目运算符 | (a 丨丨b)为真 |
! | 非 - 用来反转操作数的逻辑状态。如果条件为真,则逻辑非运算符将得到假 | 单目运算符 | (!a)为假 |
^ | 异或 - 如果两个操作数逻辑相同,则结果为假,否则为真 | 双目运算符 | (a^b)为真 |
我们可以通过“举手表决”来理解逻辑运算符
- 与 && :
a
同意了(值为true
),c
也同意了(值为true
),那这件事情肯定就OK了,所以a && c
就为true
;但是其中有一个人不同意,这件事情就不行,也就是a
和c
中,有一个为false
,a && c
就为false
。 - 或 || :这件事情只要有一个人同意了,就可以了,所以
a
和c
中,有一个为true
,a || c
就为true
。 - 非 ! :某个人原本同意,但非运算使它的结果变为相反的。
a
为true
,!a
就是false
;a
为false
,!a
就是true
。 - 异或 ^:两个人的表决结果相同,就不通过;表决结果不同,才通过。所以
a
和c
中,一真一假结果为真,其它的都是假。
其中,当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。
接下来输入以下代码,进行验证把,同学们也可自行组织代码验证一下。
public class Test {
public static void main(String args[]) {
boolean a = true;
boolean b = false;
System.out.println("a && b = " + (a && b));
System.out.println("a || b = " + (a || b));
System.out.println("!a = " + (!a));
System.out.println("a ^ b = " + (a ^ b));
}
}
运行结果:
a && b = false
a || b = true
!a = false
a & b = true
赋值运算符
赋值运算符是指将右边的操作数或运算结果赋值给左边的操作数。
赋值运算符 | 描述 | 类型 | 例子 |
---|---|---|---|
= | 赋值 - 右操作数的值赋给左侧操作数 | 双目运算符 | a=c |
+= | 加等于 - 左操作数和右操作数相加赋值给左操作数 | 双目运算符 | a+=c等价于a=a+c |
-= | 减等于 - 左操作数和右操作数相减赋值给左操作数 | 双目运算符 | a-=c等价于a=a-c |
*= | 乘等于 - 左操作数和右操作数相乘赋值给左操作数 | 双目运算符 | a=c等价于a=ac |
/= | 除等于 - 左操作数和右操作数相除赋值给左操作数 | 双目运算符 | a/=c等价于a=a/c |
%= | 取余等于 - 左操作数和右操作数取模后赋值给左操作数 | 双目运算符 | a%=c等价于a=a%c |
注意:除了上述的赋值运算符外,还有位运算和逻辑运算的赋值运算符,形式和方法同上。
接下来输入以下代码,进行验证:
public class Test {
public static void main(String args[]) {
int a = 5;
int b = 3;
b += a;
System.out.println("b += a = " + b);
b = 3;
b -= a;
System.out.println("b -= a = " + b);
b = 3;
b *= a;
System.out.println("b *= a = " + b);
b = 3;
b /= a;
System.out.println("b /= a = " + b);
b = 3;
b %= a;
System.out.println("b %= a = " + b);
}
}
运行结果:
b += a = 8
b -= a = -2
b *= a = 0
b %= a = 3
关系运算符
关系运算符生成的是一个boolean(布尔)结果,它们计算的是操作数的值之间的关系。如果关系是真实的,结果为true(真),否则,结果为false(假)。
表格中的例子中,假设变量a为3,变量b为5:
关系运算符 | 描述 | 例子 |
---|---|---|
== | 等于 - 判断两个操作数的值是否相等,如果相等则条件为真 | (a==b)为false |
!= | 不等于- 判断两个操作数的值是否相等,如果不相等则条件为真 | (a!=b)为false |
> | 大于 - 判断左操作数的值是否大于右操作数的值,如果是那么条件为真 | (a>b)为false |
< | 小于 - 判断左操作数的值是否小于右操作数的值,如果是那么条件为真 | (a<b)为true |
>= | 大于等于 - 判断左操作数的值是否大于或等于右操作数的值,如果是那么条件为真 | (a>=b)为false |
<= | 小于等于 - 判断左操作数的值是否小于或等于右操作数的值,如果是那么条件为真 | (a<=b)为true |
接下来输入以下代码,进行验证:
public class Test {
public static void main(String args[]) {
int a = 3;
int b = 5;
System.out.println("a == b = " + (a == b));
System.out.println("a != b = " + (a != b));
System.out.println("a > b = " + (a > b));
System.out.println("a < b = " + (a < b));
System.out.println("a >= b = " + (a >= b));
System.out.println("a <= b = " + (a <= b));
}
}
运行结果:
a == b = false
a != b = true
a > b = false
a < b = true
a >= b = false
a <= b = true
强调:
-
==
和!=
适用于所有的基本数据类型,其它关系运算符不适用于boolean
,因为boolean
值只有true
和false
,比较没有任何意义。 -
==
和!=
也适用于所有对象,可以比较对象的引用
是否相同。
引用:Java中的一切都是对象,但操作的标识符实际是对象的一个引用。
例:
String s;
在这里,创建的是引用
,不是对象
。创建引用后,一种安全的做法是对其进行初始化。
String s = "abc";
String s = new String("abc");
通常采用new操作符
生成一个新对象,然后将引用与该对象相关联。
来看下面的代码:
public class Test {
public static void main(String args[]) {
Integer n1 = new Integer(2);
Integer n2 = new Integer(2);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}
在上面的代码中,同学们认为输出的结果是什么呢,可能认为先是true
,再是false
,因为两个对象是相同的。尽管两个对象的内容相同,但它们的引用却不相同,==
和!=
比较的就是对象的引用,所以结果false
,再是true
,如下:
false
true
而想要比较对象的内容是否相同时,Java提供了一个特殊的方法equals()
,它不适用与基本类型
,基本类型使用==
和!=
进行比较。
来看下面的代码:
public class Test {
public static void main(String args[]) {
Integer n1 = new Integer(2);
Integer n2 = new Integer(2);
System.out.println(n1.equals(n2));
}
}
上述的代码运行结果:
true
注:但是当自己创建了一个类时,情况又会相反,因为equals()默认比较引用,除非在自己的类中覆盖equal()方法。
条件运算符
同学们从上面我们可以发现,我们把各类运算符分为了单目运算符和双目运算符,这是什么意思呢?单目运算符(或一元运算符)是只需要有一个操作数的运算符,双目运算符(或二元运算符)是需要两个操作数的运算符。
那有没有三目运算符呢?
条件运算符?:便是唯一的一个三目运算符了。
语法形式:布尔表达式?表达式1 : 表达式2
运算过程:如果布尔表达式的值为true ,则返回 表达式1 的值,否则返回 表达式2 的值。
例如:
String str = (3<2) ? "3小于2" : "3大于2";
System.out.println(str);
分析一下上面的代码,很明显3<2是false,所以返回第二个表达式,即str = "3大于2"。
Instanceof运算符
该运算符用于操作对象实例,检查该对象是否是一个待定类型(类类型或接口类型)。
instanceof运算符使用格式如下:
(Object reference variable) instanceof (class/interface type)
如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。
下面是一个例子:
String name = "James";
boolean result = name instanceof String; // 由于name是String类型,所以返回真
如果被比较的对象兼容于右侧类型,该运算符仍然返回true。
看下面的例子:
class Vehicle {}
public class Car extends Vehicle {
public static void main(String[] args){
Vehicle a = new Car();
boolean result = a instanceof Car;
System.out.println( result);
}
}
以上实例编译运行的结果如下:
true
运算符的优先级
当多个运算符出现在一个表达式中,谁先谁后?这就涉及到运算符的优先级别的问题。在一个多运算符的表达式中,运算符优先级不同会导致最后得出的结果差别甚大。
例如,(1+3)+(3+2)*2,这个表达式如果按加号最优先计算,答案就是 18,如果按照乘号最优先,答案则是 14。
再如,x = 7 + 3 * 2;这里x得到13,而不是20,因为乘法运算符比加法运算符有较高的优先级,所以先计算3 * 2得到6,然后再加7。
下表是运算符的优先级表:
优先级 | 运算符 | 关联性 |
---|---|---|
1 | () 、[] | 从左到右 |
2 | ! 、+(正)、-(负)、~、++、-- | 从右到左 |
3 | * 、/、% | 从左到右 |
4 | +、- | 从左到右 |
5 | << 、>>、 >>> | 从左到右 |
6 | <、<=、>、>=、instanceof | 从左到右 |
7 | ==、!= | 从左到右 |
8 | &(按位与) | 从左到右 |
9 | ^ | 从左到右 |
10 | 丨 | 从左到右 |
11 | && | 从左到右 |
12 | 丨丨 | 从左到右 |
13 | ?: | 从右到左 |
14 | =、+=、-=、*=、/=、%=、&=、丨=、 ^=、~=、 <<=、>>=、 >>>= | 从右到左 |
练习题
1.第一题
求出 j 的结果,写出运算步骤
public static void main(String[] args) {
int i=3,j;
j=(i++)+(i++)+(++i);
System.out.println(j);
}
它的运算结果为13,j=(i++)+(i++)+(++i)的运算步骤为(i++)=3,i=4, 第二个(i++)=4,i=5,第三个(++i)=6,i=6,之后相加,为13.
public static void main(String[] args) {
int a = 1;
a = a++;
System.out.println(a);
int b = a++ * ++a;
System.out.println(b);
}
求a,b,c最后的值
public static void main(String[] args) {
int a = 10;
int b = 10;
int c = 10;
a = b++;
c = --a;
b = a--;
System.out.println(a);
System.out.println(b);
System.out.println(c);
}