上衣篇幅中我们已经学过了字面值常量和变量,它们都可以用来表示一个数据,本节课我们要学习的是:如何使用运算符对常量和变量进行运
算。在具体讲解之前,我们需要概括下运算符和表达式的概念:
操作符:
对字面值常量或变量进行操作的
符号
,也称
运算符
。
表达式:用
操作符
把字面值常量或变量连接起来的式子(符合
Java
语
法),就称之为表达式。
案例:
操作符可以分为下面几类:
◆ 算术运算符
+
、
-
、
*
、
/
这几个操作符十分常用,较简单,我们看下述案例即可:
public static
void
main
(
String
[]
args
) {
//
定义两个
int
类型的变量
int
a
=
6
;
int
b
=
4
;
System
.
out
.
println
(
a
+
b
);
//10
System
.
out
.
println
(
a
-
b
);
//2
System
.
out
.
println
(
a
*
b
);
//24
System
.
out
.
println
(
a
/
b
);
//?
System
.
out
.
println
(
a
%
b
);
//2
//
整数相除结果是整数,要想得到小数,必须有浮点数的参与
double
c
=
a
;
System
.
out
.
println
(
c
/
4
);
}
% 求余运算符:
具体案例如下,请思考输出结果分别是什么:
public static
void
main
(
String
[]
args
) {
int
n
=
13
%
5
;
System
.
out
.
println
(
"n: "
+
n
);
// ?
n
= -
13
%
5
;
System
.
out
.
println
(
"n: "
+
n
);
// ?
n
=
13
% -
5
;
System
.
out
.
println
(
"n: "
+
n
);
// ?
n
= -
13
% -
5
;
System
.
out
.
println
(
"n: "
+
n
);
// ?
}
其输出结果为:
3
、
-3
、
3
、
-3
结论:
求余运算,结果符号只跟左操作数的符号有关
字符串相加:
+
除了可以作为加法运算符,也可以作为字符串连接符。
字符串
+
其他任意类型数据,得到的结果都是字符串
。
案例:
自增自减:
++
为自增,
--
为自减,两者使用方式类似,下面重点介绍
++
。
自增或自减有两种使用方式,分别如下:
变量名++;
++变量名;
如果单独使用,目的是对变量进行自增或自减,上述2种方式作用相同:
public static void main(String[] args) {
int
a
=
10
;
a
++
;
System
.
out
.
println
(
"a: "
+
a
);
// a: 11
a
=
10
;
++
a
;
System
.
out
.
println
(
"a: "
+
a
);
// a: 11
}
如果作为表达式使用,则两者有明显区别
public static
void
main
(
String
[]
args
) {
int
a
=
10
;
//
先保留
a
的值
10
,然后将
a
的值自增,最后将
a
之前的值
10
赋值给
b
int
b
=
a
++
;
System
.
out
.
println
(
"a: "
+
a
);
// a: 11
System
.
out
.
println
(
"b: "
+
b
);
// b: 10
a
=
10
;
//
先对
a
自增,然后获取到
a
的值
11
,赋值给
b
b
= ++
a
;
System
.
out
.
println
(
"a: "
+
a
);
// a: 11
System
.
out
.
println
(
"b: "
+
b
);
// b: 11
}
--
自减的使用方式与自增类似。
◆ 赋值运算符
除此之外,还有
<<= >>= >>>= &= ^= |=
,和上面的含义是一样的,了解过
<< >> >>> & ^ |
这几个二进制操作后,那么加上
=
号
的意思也就知道了。
public static
void
main
(
String
[]
args
) {
int
a
=
10
;
a
+=
5
;
//a = a + 5;
System
.
out
.
println
(
"a: "
+
a
);
//15
a
-=
10
;
//a = a - 10;
System
.
out
.
println
(
"a: "
+
a
);
//5
//
面试题
short
s
=
10
;
//s = s + 5; //error
s
+=
5
;
// s = (short)(s+5);
System
.
out
.
println
(
"s: "
+
s
);
}
注意
:
+=
、
-=
、
*=
、
/=
等扩展的赋值运算符,隐含了强制类型转换!
◆ 比较运算符
◆ 逻辑运算符
程序获取从键盘录入的整数值(补充内容):
java.util.Scanner
类,可以接收用户从键盘中的输入,该类是
Java
提
供好的
API
。我们在代码中导入后可以直接使用,具体使用步骤如下:
1.
导包
import java.util.Scanner;
2. 创建
Scanner
对象
Scanner sc = new Scanner(System.in);
3. 从键盘获取值
int a = sc.nextInt();
案例1:&& || 基本功能测试
//1.
导包
import
java
.
util
.
Scanner
;
public static
void
main
(
String
[]
args
) {
//2.
实例化对象
Scanner sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
println
(
"input two num: "
);
//3.
获取键盘录入的值
int
v
=
sc
.
nextInt
();
int
n
=
sc
.
nextInt
();
//
判断是否同时能被
3 5
整除
//
注意:使用
&
效果也一样
if
((
v
%
3
==
0
)
&&
(
v
%
5
==
0
)) {
System
.
out
.
println
(
"yes"
);
}
else
{
System
.
out
.
println
(
"no"
);
}
//
判断是否 是
3
的整数倍 或 是
5
的整数倍
//
注意:使用
|
效果也一样
if
((
n
%
3
==
0
)
||
(
n
%
5
==
0
)) {
System
.
out
.
println
(
"yes"
);
}
else
{
System
.
out
.
println
(
"no"
);
}
}
案例2:&& || 逻辑短路功能测试
public static
void
main
(
String
[]
args
) {
int
x
=
1
;
int
y
=
5
;
//
注意:用
&&
与
&
测试的结果不同,因为
&&
具有逻辑短路功能
//
逻辑短路:如果计算完第一个表达式,得到的结果能够决定整个表
达式结果的话,则不再运算第二个表达式
boolean
f
=
(
x
>
4
)
&&
(
y
++ >
5
);
//
不会运算
y++ > 5
//boolean f = (x > 4) & (y++ > 5);
System
.
out
.
println
(
"f: "
+
f
);
//false
System
.
out
.
println
(
"y: "
+
y
);
//5
// !
逻辑非
if
(
!
f
) {
System
.
out
.
println
(
"true"
);
}
else
{
System
.
out
.
println
(
"false"
);
}
}
案例3:! 逻辑非功能测试
public static
void
main
(
String
[]
args
) {
int
x
=
1
;
int
y
=
5
;
System
.
out
.
println
(
!
(
x
>
y
));
//!false
System
.
out
.
println
(
!!
(
x
>
y
));
//!!false
System
.
out
.
println
(
!!!
(
x
>
y
));
//!!!false
}
◆ 移位运算符
如果要进行移位操作,
则需要先获取操作数的二进制形式(补码)
,然后按位进行操作。
右移:
>>
低位抛弃,高位补【符号位的值】
>>>
低位抛弃,高位补
0
public static
void
main
(
String
[]
args
) {
// 0 0(23) 0000 1010
int
a
=
10
;
System
.
out
.
println
(
"a: "
+
a
);
// 0 0(23) 0000 1010
// 00 0(23) 000 0101 [0] ==> 5
int
b
=
a
>>
1
;
System
.
out
.
println
(
"a >> 1: "
+
b
);
// 000 0(23) 0000 10 ==> 2
b
=
a
>>
2
;
System
.
out
.
println
(
"a >> 2: "
+
b
);
//
负数移位操作
a
= -
10
;
//
获取
-10
的二进制补码:
//
原
1 0(23) 0000 1010
//
反
1 1(23) 1111 0101
//
补
1 1(23) 1111 0110
//
运算
: 111 1(23) 1111 01 [10]
b
=
a
>>
2
;
//
高位补
1
负
//
结果推导:补
1 1(23) 1111 1101
// - 1
//
反
1 1(23) 1111 1100
//
保留符号位,其他位取反
//
原
1 0(23) 0000 0011
//
结果:
-3
System
.
out
.
println
(
"-10 >> 2: "
+
b
);
b
=
a
>>>
2
;
// -10
补:
1 1(23) 1111 0110
// >>> 2
位,高位补
0
// 00 1 1(23) 1111 01
//
结果
:
很大的一个正整数
1073741821
System
.
out
.
println
(
"-10 >>> 2: "
+
b
);
}
左移:
<<
高位抛弃,低位补
0
//
左移
:
高位抛弃 低位补
0
public static
void
main
(
String
[]
args
) {
int
a
=
10
;
System
.
out
.
println
(
"a: "
+
a
);
// 10
int
b
=
a
<<
1
;
System
.
out
.
println
(
"a << 1: "
+
b
);
// 20
b
=
a
<<
2
;
System
.
out
.
println
(
"a << 2: "
+
b
);
// 40
b
=
a
<<
3
;
System
.
out
.
println
(
"a << 3: "
+
b
);
// 80
//
结果:每左移
1
位,等同
== (
值
* 2)
a
= -
10
;
b
=
a
<<
2
;
// -10
补码:
1 1(23) 1111 0110
//
左移
2
位,结果:
// 1(22) 1111 011000
//
即:
1 1(23) 1101 1000
// -1
得反码:
1 1(23) 1101 0111
//
保留符号位,其他为取反,得原码:
//
原
: 1 0(23) 0010 1000 ==> -40
System
.
out
.
println
(
"a << 4: "
+
b
);
//
如果左移位数太多,超出了数值表示范围,如何处理?
//
数值
<< n
等同 数值
<< (n%
当前数值所占比特位数
)
b
=
a
<<
33
;
System
.
out
.
println
(
"a << 33: "
+
b
);
//20
System
.
out
.
println
(
"a << (33%32): "
+
b
);
//20
}
小结
:
每左移
1
位,等
v
同 值
* 2 数值 左移
n
位
(
较大
)
,等同 数值
<< (n%
当前数值所占比特位数
)
◆ 位运算符
案例1:位运算符基本使用
//1.
导包
import
java
.
util
.
Scanner
;
//
从键盘录入两个数 进行 位运算
public static
void
main
(
String
[]
args
) {
//2.
实例化对象
Scanner sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
println
(
"input two num: "
);
// 10 0 0(23) 0000 1010
int
n1
=
sc
.
nextInt
();
// 3 0 0(23) 0000 0011
int
n2
=
sc
.
nextInt
();
//&: 1&1 == 1 0&? == 0
// 0 0(23) 0000 1010
//& 0 0(23) 0000 0011
// 0 0(23) 0000 0010 ==> 2
int
value
=
n1
&
n2
;
System
.
out
.
println
(
"n1 & n2: "
+
value
);
// 0 0(23) 0000 1010
//| 0 0(23) 0000 0011
// 0 0(23) 0000 1011 ==> 11
value
=
n1
|
n2
;
System
.
out
.
println
(
"n1 | n2: "
+
value
);
// 0 0(23) 0000 1010
//^ 0 0(23) 0000 0011
// 0 0(23) 0000 1001 ==> 9
value
=
n1 ^ n2
;
System
.
out
.
println
(
"n1 ^ n2: "
+
value
);
// 0000 1010
byte
num
=
10
;
//~ 0000 1010
// 1111 0101 ==> -?
//
原码
<->
反码
<->
补码
//
补
: 1111 0101
//
反:补码
-1
// 1111 0100
//
原
:
反码保留符号位,其他位取反
// 1000 1011
//
结果:
-11
value
=
~num
;
System
.
out
.
println
(
"~num: "
+
value
);
}
案例
2
:
^
特殊用法
不使用中间变量得前提下,交换
2
个变量的值。
public class
Test07
{
public static
void
main
(
String
[]
args
) {
int
x
=
10
;
int
y
=
20
;
swap
(
x
,
y
);
System
.
out
.
println
(
"--------------"
);
swap2
(
30
,
40
);
}
//
定义方法,交换两个整形数的值
//
修饰符 返回值类型 函数名
(
形式参数列表
) {
//
方法体语句
;
//}
public static
void
swap
(
int
a
,
int
b
) {
System
.
out
.
println
(
"
交换前:
a: "
+
a
+
",b: "
+
b
);
int
t
=
a
;
a
=
b
;
b
=
t
;
System
.
out
.
println
(
"
交换后:
a: "
+
a
+
",b: "
+
b
);
}
//
不借助第三个变量,完成
2
个数的交换
public static
void
swap2
(
int
a
,
int
b
) {
System
.
out
.
println
(
"
交换前:
a: "
+
a
+
",b: "
+
b
);
//
一个数 异或 另一个数
2
次,结果是自己
a
=
a ^ b
;
b
=
a ^ b
;
// a^b^b ==> a
a
=
a ^ b
;
// a^b^a ==> b;
System
.
out
.
println
(
"
交换后:
a: "
+
a
+
",b: "
+
b
);
}
}
扩展练习:
使用位操作符,对变量
a
(
10
)进行某一位置
0
或置
1
操作。
public class
Test07
{
public static
void
main
(
String
[]
args
) {
int
a
=
10
;
/*
题目:将
a
的第
5
位 置为
1
解题思路分析
:
只要得到
0 0(23) 0001 0000
,然后和
a
进行或运算
即可得到
如何得到
0 0(23) 0001 0000
?
1<<(5-1)
运算即可得到:
0 0(23) 0001 0000
*/
int
b
=
a
|
(
1
<<
(
5
-
1
));
System
.
out
.
println
(
"b: "
+
b
);
//
调用方法实现
b
=
setBit1
(
10
,
5
);
System
.
out
.
println
(
"b: "
+
b
);
//26
b
=
setBit0
(
10
,
4
);
System
.
out
.
println
(
"b: "
+
b
);
//2
}
//
将
value
的第
n
位置为
1
,结果返回
public static
int
setBit1
(
int
value
,
int
n
) {
int
r
=
value
|
(
1
<<
(
n
-
1
));
return
r
;
}
//
将
value
的第
n
位置为
0
,结果返回
// 10 4
// 0 0(23) 0000 1010
//& 1 1(23) 1111 0111
// 0 0(23) 0000 1000
// 0 0(23) 0000 0001
public static
int
setBit0
(
int
value
,
int
n
) {
int
r
=
~
(
1
<<
(
n
-
1
))
&
value
;
return
r
;
}
}
◆ 三目运算符
也称条件运算符。
格式
:
(
关系表达式
) ?
表达式
1 :
表达式
2;
关系表达式成立,返回表达式
1
,否则返回表达式
2
案例:
import
java
.
util
.
Scanner
;
//
从键盘录入
2
个整数,比较大小
public class
Test08
{
public static
void
main
(
String
[]
args
) {
Scanner sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
println
(
"input two num: "
);
int
a
=
sc
.
nextInt
();
int
b
=
sc
.
nextInt
();
int
max
=
(
a
>
b
)
?
a
:
b
;
int
min
=
(
a
<
b
)
?
a
:
b
;
System
.
out
.
println
(
"max: "
+
max
);
System
.
out
.
println
(
"min: "
+
min
);
}
}