Java 程序设计基础之操作符

关于 Java 程序设计语言的 基础语法 部分,前面我们已经详细了解过了 Java 中的字面值,变(常)量,数据类型,本文我们来看 Java 基础语法的另一个重要组成部分——操作符,Java 中提供了丰富的操作符支持。

Java 中的操作符

1 –> 特殊概念

–> 优先级 & 结合性

Java 中的操作符,等价于数学中的运算符,也是有优先级,和结合性的概念的。

这也就是说,当一个表达式中出现多种操作符时,执行的先后顺序不仅要遵守操作符优先级规定,还要受操作符结合性的约束,以便确定是自左向右进行运算?还是自右向左进行运算?

–> 操作数

操作符进行运算时,所操作(依赖)的数据

–> 操作符按照【操作数的数量】可以分为:单目运算符、双目运算符和三目运算符。

2 –> 操作符类别

Java 中最基本的操作符可归纳为以下 6 大类:

  1. 算术操作符
  2. 赋值操作符
  3. 关系操作符
  4. 逻辑操作符
  5. 条件操作符
  6. 位操作符

详细解读上面提到的 6 种 Java 基本操作符用法:

算术操作符

Java 语言中,算术操作符的功能是对数据进行算术运算。这里为了方便记忆,特将算术运算分为三类:

  1. 基本算术操作符:+(加) -(减) *(乘) /(除)%(取模/余)
  2. 基本算术赋值操作符:+=(加赋值)-=(减赋值)*=(乘赋值)/=(除赋值)%=(取模赋值)
  3. 算术单目运算符:-(负) ++(自增) –(自减)

基本算术操作符

Java 算术操作符中,最基本的算术运算就是:

1
+(加) -(减) *(乘) /(除)%(取模/余)

上述运算符,和我们平常接触的数学运算具有相同的含义。

隐藏运算规则:

  • 如果表达式中有任何运算单元的长度超过 int,那么运算结果就按照最长的长度计算
  • 如果表达式中有任何运算单元的长度都不超过 int,那么运算结果就按照 int 来计算
1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorld {
public static void main(String[] args) {

int a = 5;
long b = 6;
int c = (int) (a+b); // a+b 的运算结果是 long 型,所以要进行强制转换

byte d = 1;
byte e= 2;
byte f = (byte) (d+e); //虽然 a b 都是 byte 类型,但是运算结果是 int 类型,需要进行强制转换
}
}

基本算术赋值操作符

算术赋值运算符只是一种简写(算术操作符 && 赋值运算符的一种应用),一般用于变量自身的变化:

运 算 符 名 称 例 子 等价于
+= 加赋值 a += b + 3 a = a + b + 3
-= 减赋值 a -= b a = a - b
*= 乘赋值 a *= b a = a*b
/= 除赋值 a /= b a = a/b
%= 取余赋值 a %= b a = a%b

算术单目操作符

算术操作符中的,单目运算符有 3 个,分别表示:-(负) ++(自增) –(自减)。

其中,-(负)最为简单,就是数学上的含义,不做过多说明,下面重点来看自增、自减的使用。

使用原则:

  • 自增/自减只能作用于变量,不允许对常量、表达式等进行操作;
  • 自增/自减运算可以用于整数类型 byte、short、int、long;浮点类型 float、double;字符串类型 char
  • 自增/自减运算(Java V1.5 以上)可以用于基本类型对应的包装器类 Byte、Short、Integer、Long、Float、Double 和 Character
  • 自增/自减运算作用于变量自身加/减 1,放在操作数的前面或后面都是允许的。

1 –> 自增 & 自减

i++(自增)i –(自减):在变量 i 原来的基础上,增加 1 或者减少 1。

1
2
3
4
5
6
7
8
9
public class HelloWorld {
public static void main(String[] args) {

int i = 4;
i++;
System.out.println(5); // 输出为6

}
}

2 –> 前后置区别

以 ++ 为例,– 同理。

1
2
3
int i = 4;
i++; // 先取值,再运算
++i; // 先运算,再取值

具体测试例:

1
2
3
4
5
6
7
8
9
10
11
public class HelloWorld {
public static void main(String[] args) {
int i = 5;
System.out.println(i++); // 输出5
System.out.println(i); // 输出6

int j = 5;
System.out.println(++j); // 输出6
System.out.println(j); // 输出6
}
}

思考:下面的 j 是 多少?

1
2
int i = 1;
int j = ++i + i++ + ++i + ++i + i++; // 2 + 2(3) + 4 + 5 + 5 = 18

赋值操作符

赋值运算符是指为 变量或常量 指定数值的符号。使用很简单,其语法格式如下所示:

1
变量名称 = 表达式内容

它是双目运算符,左边的操作数必须是变量,不能是常量值或表达式;右侧可以为字面值,表达式。

注意:不要将赋值运算符与相等运算符 “==” 混淆。

示例:

1
2
3
4
5
6
public class HelloWorld {
public static void main(String[] args) {
/* 首先进行 5+5 的运算,得到结果 10,然后把 10 这个值,赋给变量 i */
int i = 5+5;
}
}

关系操作符

关系操作符(relational operators)也可以称为:“比较操作符”,用来比较判断两个变量或常量的大小。

运算结果是 boolean 型。当操作符对应的大小关系成立时,运算结果是 true,否则是 false

比较操作符的含义及其实例应用:

1 –> 大于操作符(>)

只支持左右两边操作数是数值类型。如果前面变量的值大于后面变量的值, 则返回 true。

1
2
# false
2 > 3

2 –> 大于等于操作符(>=)

只支持左右两边操作数是数值类型。如果前面变量的值大于等于后面变量的值, 则返回 true。

1
2
# true
4 >= 2

3 –> 小于操作符(<)

只支持左右两边操作数是数值类型。如果前面变量的值小于后面变量的值,则返回 true。

1
2
# true
2 < 3

4 –> 小于等于操作符(<=)

只支持左右两边操作数是数值类型。如果前面变量的值小于等于后面变量的值, 则返回 true。

1
2
# false
4 <= 2

5 –> 相等运算符(==)

5.1 数值类型比较:

无论它们的数据类型是否相同,只要它们的值相等,也都将返回 true。

1
2
3
4
5
6
7
8
# true
4 == 4
# true
97 == 'a'
# true
5.0 == 5
# false
true == false

等于操作符支持,两个 boolean 类型的值进行比较。但注意:boolean 类型的变量、值不能与其他任意类型的变量、值使用 == 进行比较。

5.2 引用类型比较:

只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。


6 –> 不相等运算符(!=)

6.1 数值类型比较:

如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值不相等,也都将返回 true。

1
2
# true
4 != 2

6.2 引用类型比较:

如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。

=============================================

You Know More:

  • == 和 != 可以应用于基本数据类型和引用类型。当用于引用类型比较时,比较的是两个引用是否指向同一个对象,但实际开发过程多数情况下,只是比较对象的内容是否相当,不需要比较是否为同一个对象。
  • 基本类型的变量、值不能和引用类型的变量、值使用 == 进行比较;boolean 类型的变量、值不能与其他任意类型的变量、值使用 == 进行比较;如果两个引用类型之间没有父子继承关系,那么它们的变量也不能使用 == 进行比较。

逻辑操作符

逻辑运算符把各个关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。

逻辑运算符的用法、含义及实例:

1 –> 逻辑与(&) 和 短路与(&&)

两边的运算单元都是布尔值,运算规则:

  • 都为真时,才为真
  • 有假即假

区别:

  • 逻辑与 两侧,都会被运算
  • 短路与 只要第一个是false,第二个就不进行运算了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloWorld {
public static void main(String[] args) {
//长路与 无论第一个表达式的值是true或者false,第二个的值,都会被运算
int i = 2;
System.out.println( i== 1 & i++ ==2 ); //无论如何i++都会被执行,所以i的值变成了3
System.out.println(i);

//短路与 只要第一个表达式的值是false的,第二个表达式的值,就不需要进行运算了
int j = 2;
System.out.println( j== 1 && j++ ==2 ); //因为j==1返回false,所以右边的j++就没有执行了,所以j的值,还是2
System.out.println(j);

}
}

2 –> 逻辑或(|) 和 短路或(||)

两边的运算单元都是布尔值,运算规则:

  • 有真即真
  • 都为假时,才为假

区别:

  • 逻辑或(|)两侧都会被运算
  • 短路或(||) 只要第一个是 true 的,第二个就不进行运算了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloWorld {
public static void main(String[] args) {
//长路或 无论第一个表达式的值是true或者false,第二个的值,都会被运算
int i = 2;
System.out.println( i== 1 | i++ ==2 ); //无论如何i++都会被执行,所以i的值变成了3
System.out.println(i);

//短路或 只要第一个表达式的值是true的,第二个表达式的值,就不需要进行运算了
int j = 2;
System.out.println( j== 2 || j++ ==2 ); //因为j==2返回true,所以右边的j++就没有执行了,所以j的值,还是2
System.out.println(j);

}
}

3 –> 取反(!)

真变为假,假变为真。

1
2
3
4
5
6
7
8
9
public class HelloWorld {
public static void main(String[] args) {
boolean b = true;

System.out.println(b); //输出true
System.out.println(!b);//输出false

}
}

4 –> 异或(^)

不同,返回真;相同,返回假。

1
2
3
4
5
6
7
8
9
10
public class HelloWorld {
public static void main(String[] args) {
boolean a = true;
boolean b = false;

System.out.println(a^b); //不同返回真
System.out.println(a^!b); //相同返回假

}
}

注意:短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先

考虑使用短路与和短路或。


条件操作符

Java 中提供了一个特别的三目运算符,经常用于取代某个类型的 if-then-else 语句。

使用条件操作符的一般语法结构为:

result = <expression> ? <statement_1> : <statement_3>;

其中,expression 是一个布尔表达式。当 expression 为真时,执行 statement_1, 否则就执行 statement_3。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HelloWorld {
public static void main(String[] args) {

int i = 5;
int j = 6;

int k = i < j ? 99 : 88;

// 相当于
if (i < j) {
k = 99;
} else {
k = 88;
}

System.out.println(k);

}
}

位操作符

Java 中定义的位运算(bitwise operators),按位运算表示按每个二进制位(bit)进行计算。

可以直接对 整数类型 的二进制位进行操作,这些整数类型包括 long,int,short,char 和 byte。其操作数和运算结果都是整型值。

Java 语言中的位运算符分为 位逻辑操作符位移操作符 以及位赋值操作符

  • 位逻辑操作符:&(与)、|(或)、~(非)和 ^(异或)
  • 位移操作符:将操作数向左(<<)或者右(>>),移动指定的二进制位数

这里注意,位逻辑操作符和逻辑操作符的区别。


1 –> 整数的二进制

位操作,都是对整型操作数二进制而言的。

Java 中可以通过 Integer.toBinaryString() 方法,将一个十进制整数转换为一个二进制字符串

1
2
3
4
5
6
7
8
9
10
public class HelloJava {

public static void main(String[] args) {
// TODO Auto-generated method stub
int i = 5;
String string = Integer.toBinaryString(i);
System.out.println(string);
}

}

2 –> 位逻辑操作符

2.1 –> 位与(&)

运算规则:

参与运算的操作数,低位对齐,高位不足的补零;如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。

例如:100&0


2.2 –> 位或(|)

运算规则:

参与运算的操作数,低位对齐,高位不足的补零;如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0。

例如:11|7


2.3 –> 位异或(^)

运算规则:

其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。

例如:11^7


2.4 –> 位取反(~)

运算规则:

只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。

例如:~10

注意:位操作符的操作数只能是整型或者字符型数据以及它们的变体,不用于 float、double 或者 long 等复杂的数据类型。


3 –> 位移操作符

位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数。

位移操作符说明:

运算符 含义 实例 结果
» 右移位运算符 8»1 4
« 左移位运算符 9«2 36

3.1 –> 左位移(<<)

运算规则:

按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。

例如:11 –> 22


3.2 –> 右位移(>>)

运算规则:

按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。

例如:11 –> 5

=======================================================

带符号右移与无符号右移:

1 –> 带符号右移:>>

对于正数, 带符号右移 >> 会把所有的位右移,并在最前面补0
对于负数, 带符号右移 >> 会把所有的位右移,并在最前面补1

2 –> 无符号右移:>>>

如果是一个负数,那么对应的二进制的第一位是1。无符号右移>>>会把第一位的1也向右移动,导致移动后,第一位变成0,这样就会使得负数在无符号右移后,得到一个正数。


4 –> 位赋值操作符

所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式:

运算符 含义 实例 结果
&= 按位与赋值 num1 &= num2 等价于 num 1=num 1 & num2
|= 按位或赋值 num1 |= num2 等价于 num 1=num 1
^= 按位异或赋值 num1 ^= num2 等价于 num 1=num 1 ^ num2
«= 按位左移赋值 num1 «= num2 等价于 num 1=num 1 « num2
»= 按位右移赋值 num1 »= num2 等价于 num 1=num 1 » num2

============================================

位赋值实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class HelloJava {

public static void main(String[] args) {
// TODO Auto-generated method stub
int a = 1;
int b = 2;
int c = 3;

a &= 4;
System.out.println(a);
a |= 4;
System.out.println(a);
a ^= c;
System.out.println(a);
a -= 6;
System.out.println(a);
b >>= 1;
System.out.println(b);
c <<= 1;
System.out.println(c);
}

}

输出:

1
2
3
4
5
6
0
4
7
1
1
6

操作符优先级

Java 中操作符优先级助记口诀:

单目乘除为关系,逻辑三目后赋值

口诀解释:

  • 单目:单目操作符 –> !(取反)+(正) –(负数) ++/ –(自增自减) ~
  • 乘除:算数操作符中的 *(乘) /(除) %(取模)–> 后 +(加)-(减)
  • 为:位移操作符 << (左移)>>(右移)
  • 关系:关系运算符> (大于)<(小于) >=(大于等于) <=(小于等于)==(等于) !=(不等于)
  • 逻辑:逻辑操作符 &&(短路与) ||(短路或) &(逻辑与) |(逻辑或) ^ (异或)
  • 三目:三目操作符 A > B ? X : Y
  • 后:无意义,仅仅为了凑字数
  • 赋值:=(赋值)+=/-+/*=//=/%=(算术赋值)&=/|=/^=/~=(位逻辑赋值)<<=/>>=(位移赋值)

操作符优先级:

优先级 运算符 结合性
1 ()、[]、{} 从左向右
2 !、+、-、~、++、– 从右向左
3 *、/、% 从左向右
4 +、- 从左向右
5 «、»、>>> 从左向右
6 <、<=、>、>=、instanceof 从左向右
7 ==、!= 从左向右
8 & 从左向右
9 ^ 从左向右
10 | 从左向右
11 && 从左向右
12 || 从左向右
13 ?: 从右向左
14 =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= 从右向左

实际的开发中,不需要去记忆运算符的优先级别,也不要刻意的使用运算符的优先级别,对于不清楚优先级的地方使用小括号去进行替代。


Scanner

截至目前为止,学习了使用 System.out.println(“”) 向控制台输出数据。

那么,如何从控制台输入数据?

使用Scanner类,需要在最前面加上

import java.util.Scanner;

表示导入这个类,才能够正常使用。

Scanner 读取整数

1
2
3
4
5
6
7
8
9
10
11
import java.util.Scanner;

public class HelloWorld {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int a = s.nextInt();
System.out.println("第一个整数:"+a);
int b = s.nextInt();
System.out.println("第二个整数:"+b);
}
}

Scanner 读取浮点数

1
2
3
4
5
6
7
8
9
10
import java.util.Scanner;

public class HelloWorld {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
float a = s.nextFloat();
System.out.println("读取的浮点数的值是:"+a);

}
}

Scanner 读取字符串

1
2
3
4
5
6
7
8
9
import java.util.Scanner;

public class HelloWorld {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String a = s.nextLine();
System.out.println("读取的字符串是:"+a);
}
}

读取了整数后,接着读取字符串:

如果在通过nextInt()读取了整数后,再接着读取字符串,读出来的是回车换行:”\r\n”,因为nextInt仅仅读取数字信息,而不会读取回车换行”\r\n”。

所以,如果在业务上需要读取了整数后,接着读取字符串,那么就应该连续执行两次nextLine(),第一次是取走回车换行,第二次才是读取真正的字符串。

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.Scanner;

public class HelloWorld {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int i = s.nextInt();
System.out.println("读取的整数是"+ i);
String rn = s.nextLine();
String a = s.nextLine();
System.out.println("读取的字符串是:"+a);
}
}

Scanner Close

使用之后记得关闭 Scanner,防止消耗资源

scan.close();


Author

Waldeinsamkeit

Posted on

2017-10-14

Updated on

2023-01-16

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.