作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦
CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者
在前一篇文章中,壹哥给大家讲解了Java数据类型之间的转换,包括自动类型转换、强制类型转换、隐含的强制类型转换等问题。且在上一篇文章中,我还简单地给大家提到了Java的类型提升。在类型提升的案例中,我们涉及到了Java里的运算符。有的小伙伴会很好奇,Java里的运算符都有哪些呢?加减乘除这些符号都有吗?实际上,Java中的运算符不仅仅只有加减乘除哦,还有很多其他的运算符。那么今天壹哥就用一篇专门的文章,给大家讲解运算符相关的知识。
------------------------------前戏已做完,精彩即开始------------------------------------------------------------------
全文大约【6400】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......
电脑的大名之所以被称为”计算机“,是因为它最基本、最起初的作用就是进行数学运算。为了实现计算功能,Java为我们提供了多种运算符用于各种计算,比如算术运算符(+ - * /)、 关系运算符(< > ==)、逻辑运算符、位运算符、条件运算符等等。
如果我们把运算符按照功能来分,可以分为算术运算符、关系运算符、赋值运算符、逻辑运算符、位运算符、三目运算符、逗号运算符等各种运算符。
如果按照操作数的数目来分,可以把这些运算符分为单目运算符、双目运算符和三目运算符,分别对应于1个、2个、3个操作数。
我们把运算符能够连接操作数的个数,称为运算符的目,Java中运算符的目有三种:
- 单目运算符:只能连接一个操作数,如“+ +”、”--”;
- 双目运算符:可以连接两个操作数,Java语言中多数运算符都属于双目运算符,如“+、-、*”等;
- 三目运算符:可以连接三个操作数,Java语言中只有一个三目运算符,即条件运算符”? :“。
运算符的优先级是指在表达式中出现多个不同的运算符,在进行计算时运算符执行的先后次序。比如算术运算符中,乘除运算符的优先级高于加减运算符的优先级。在Java语言中,不同的运算符具有不同的优先级,我们在开发时要优先处理优先级高的运算符。参考下图:
这么多的优先级规则,你很难记得住,其实你也不必记忆,我们在使用时直接加括号就可以了,和数学里的规则一样。
运算符的结合方向又称为结合性,是指当一个操作数连接两个相同优先级的运算符时,会按运算符所规定的结合方向进行处理。Java中各运算符的结合性分为两种,分别为左结合性(自左向右)和右结合性(自右向左)。比如常见的+、-、*、/等运算就是自左向右,而Java里的=赋值运算,则是从右向左。
在Java中,所有的数学运算都是从左向右进行运算的,其他的大部分运算也是遵守从左向右的规则。但一元运算符,赋值运算符和三目运算符例外,他们是从右向左进行运算的。
了解完这些基本的知识之后,接下来壹哥就通过一些代码案例,分别给大家讲解一下这几种运算符的用法。
算术运算符与我们在数学中学习的计算符号一样,主要用在数学表达式中,常见的算术运算符有:
+ - * / % ++ --
这几个符号的功能如下表所示:
操作符 |
描述 |
案例(A=5,B=10) |
+ |
加法 - 相加运算符两侧的值;字符串拼接 |
A + B = 15 |
- |
减法 - 左操作数减去右操作数 |
A – B = -5 |
* |
乘法 - 相乘操作符两侧的值 |
A * B = 50 |
/ |
除法 - 左操作数除以右操作数 |
B / A = 2 |
% |
取余 - 左操作数除以右操作数的余数 |
B % A = 0 |
++ |
自增: 操作数的值增加1 |
B++ 或 ++B = 11(区别见下文) |
-- |
自减: 操作数的值减少1 |
B-- 或 --B = 9(区别见下文) |
壹哥在这里设计了如下案例,大家要跟着练习哦。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//算术运算符
//注意类型提升:两个数计算,结果取决于范围大的数!比如两个int计算,结果还是int;
//而int与浮点数进行计算,则结果为浮点数,即结果变成更大范围的类型,这就是类型提升!
int a = 10;
//double b = 20.0;
int b=20;
//+号的第1个作用:数学计算
System.out.println(a+b);
System.out.println(a-b);
System.out.println(a*b);
//两个int类型相除或相乘,结果依然是int,不会出现小数哦!而且会向下取整。
System.out.println(a/b);
System.out.println(a%b);
//除法和取模运算中,右操作数不能取0
System.out.println(a/0);
}
}
我们要特别注意,整数由于存在范围的限制,如果计算结果超出了范围,就会产生溢出。而溢出不会出错,但会得到一个奇怪的结果。
另外壹哥还要提醒大家一下,在Java中的除法和取模运算,和数学中的要求一样,是不能做除零操作的,否则在运行时会产生异常哦!这里会产生java.lang.ArithmeticException: / by zero
的异常。
我们在进行数值计算时,要注意类型提升的问题。当算术表达式中包含不同的基本类型值时,整个算术表达式的类型会进行自动提升。基本的提升规则为:
为了计算方便,Java会将小于4个字节的类型,在计算时将其隐形提升到int类型。所以byte类型、short类型和char类型会被提升为int类型,不管是否有其他类型参与运算。也就是说,整个表达式的类型会自动提升到与表达式中最高等级的操作数相同的类型。所以两个数值进行计算,结果取决于范围更大的那个数!比如两个int计算,结果是int。而int与浮点数进行计算,则结果为浮点数,即结果变成更大范围的类型,这就是类型提升!
提升等级顺序为:
byte、short、char --> int --> long --> float --> double
所以由于类型提升的原因,我们在开发时很少使用byte或者short来定义整数。也很少会使用char类型定
义字符,而是使用字符串类型,更不会使用char类型做算术运算。
Java中的+号有2个功能,一是可以进行加法操作,二是可以进行字符串拼接。尤其是在进行字符串拼接时,要考虑自左向右的结合性。当字符串在前,数字在后,执行字符串拼接操作;当数字在前,字符串字后,先计算出结果,再进行字符串的拼接。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//+号的第2个作用:字符串拼接,自左向右的结合性,字符串在前,数字在后,执行字符串拼接操作。
System.out.println("hello"+1+2); //hello12
//自左向右的结合性:数字在前,字符串字后,先计算出结果,再进行字符串的拼接。
System.out.println(1+2+"hello"); //3hello
System.out.println(1+2+"hello"+3+4);//3hello34
}
}
%是取余符号,我们可以进行取余运算,也叫做取模运算。另外%在Java中不但可以对整数进行取模,还可以对double进行取模操作。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
int c = 34;
//获取c这个数据中的十位,执行整除
System.out.println(c/10);
//获取c这个数据中的个位
System.out.println(c%10);
}
}
对初学者来说,有两个符号可能会让你比较懵圈,一个是++,一个是--,这两个符号分别叫做自增和自减运算符。++是自增符号,根据++在变量前或变量后的位置不同,也具有不同的特点,--自减符号同样如此。++和--具有如下特点:
- ++和-- 既可以放在变量的后边,也可以放在变量的前边;
- 单独使用时, ++和-- 无论是放在变量的前边还是后边,结果都是一样的;
- 参与操作时,如果放在变量的后边,会先使用变量参与操作,再取变量的值进行++或者--;
- 参与操作时,如果放在变量的前边,会先取变量的值进行++或者--,后使用变量参与操作;
- 只有变量才能使用自增/自减运算符,常量不能使用自增与自减符号,因为常量不允许被修改。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//++自增 与 --自减操作
int d = 10;
d++; //d = d + 1; 先使用,再自增
System.out.println(d); //11
++d;//先自增,再使用
System.out.println(d); //12
//先使用再自增:在本语句中,先使用变量d,在本语句结束之后再对变量d进行自增。
System.out.println(d++); //12 13
//先自增再使用:在本语句中,先对变量d进行自增,然后把自增后的结果在语句中进行输出。
System.out.println(++d); //14
//这个案例比较复杂,你好好琢磨一下吧
int x = 10;
int y = 8;
//执行过程:10 - 9 + 8 + 10 - 7 =12
System.out.println(x++ - --x + y-- + x++ - --y);
}
}
【++变量】变量先+1,然后使用变量+1之后的值;【变量++】先使用变量原来的值,表达式结束时给变量+1。所在在本案例中,如果++在变量之后,比如d++,具有“先使用,再自增”的特点。如果++在变量之前,比如++d,具有“先自增,再使用”的特点。--自减符号也是如此。壹哥不建议初学者把++运算混入到常规运算中,容易把你给搞懵逼哦。
与本节内容相关的配套视频链接如下:
bilibili html5 player
在Java中,“=”是赋值运算符,而不是我们通常认知中的“等号”。赋值运算符用于将“=”右侧表达式的结果,赋值给“=”左侧的变量。另外,除了“=”这个赋值符号之外,还有另外几个扩展的赋值符号,所以目前常用的赋值符号有如下几个:
= += -= *= /= %=
以下是几个赋值运算符的基本使用案例。在下面的案例中,大家要注意除法的计算结果哦。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//=赋值运算符
int a = 10;
a += 2; //12,相当于 a=a+2;
System.out.println("a="+a);
a -= 3; //9,a = a - 3;
System.out.println("a="+a);
a *= 4; //36,a = a * 4;
System.out.println("a="+a);
//注意:Java中的除法,36/5=7哦,不会等于7.2,想想这是为什么?
a /= 5; //7,a = a / 5;
System.out.println("a="+a);
a %= 6; //1,a = a % 6;
System.out.println("a="+a);
}
}
为了让大家更好地理解赋值运算符,壹哥再给大家扩展一个案例。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//=赋值运算符
//笔试题:short s1 = 1; short s2 = 1; s2 = s1 + s2的结果是什么? s2 += s1的结果是什么?
short s1 = 1;
short s2 = 1;
//类型提升:s1+s2变成了int类型
//此行代码会报错,因为运算中s提升为int类型,运算结果int赋值给short可能损失精度
// s2 = s1 + s2; //错误
//此行代码没有问题,这里隐含了强制类型转换,相当于s = (short) (s + 10);
s2 += s1; // 正确
System.out.println(s2);
}
}
在这个案例中,我们一定要注意类型提升的问题。两个short变量s1和s2,s1+s2时会进行类型提升变成int,所以必须对结果进行强制类型转换才行,如下图所示:
但是当我们使用s2+=s1语句时,虽然计算结果与s2=s1+s2是相同的,但内部的执行原理却不同,这是因为扩展的赋值运算符都隐含了强制类型转换。s2 = s1 + s2;
此行代码会报错,这是因为运算中s变量会提升为int类型,运算结果int赋值给short可能会损失精度。
而在s2+=s1语句中就没有问题,因为这里隐含了强制类型转换,相当于s2 = (short) (s2 + s1);
不用进行再额外强制类型转换,这一点我们一定要注意!
PS:本节内容相关视频,与上一节视频是同一视频哦。
在Java中,关系运算符,又叫做比较运算符, 或者叫做布尔运算符,主要是用于比较两个表达式的结果。常用的赋值符号有如下几个:
> >= < <= == !=
接下来我们再通过一些代码案例,来学习一下关系运算符的用法吧。我们在使用比较运算时,最终都会得到一个布尔类型的值。且在进行比较运算时,一定要注意其优先级。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
// 关系运算符
int a = 10;
int b = 20;
System.out.println(a > b);
System.out.println(a >= b);
System.out.println(a < b);
System.out.println(a <= b);
System.out.println(a == b);
System.out.println(a != b);
// 判断奇数与偶数
// 偶数条件: a % 2 == 0
// 奇数条件: a % 2 != 0
System.out.println("a != b " + (a != b));
System.out.println("a % 2 != 0 " + (a % 2 != 0));
}
}
PS:本节内容相关视频,也与上一节视频是同一视频哦。
Java中的逻辑运算符, 主要有3个:逻辑与&&、逻辑或||、逻辑非!,如下所示:
&& || !
Java中的逻辑运算符,其实和数学中的与、或、非意思一致。 逻辑运算符大多数会和其他的运算符一起使用,主要做一些简单或复杂的逻辑运算。且通常都会和 if、for等逻辑表达式一起使用,使用格式为:表达式1 逻辑运算符 表达式2
接下来我们通过一个案例来演示逻辑运算符该如何使用。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
// 逻辑运算符,结果是boolean类型
int a = 17;
//a是否是一个偶数且大于10
//短路与:如果条件表达式中,前面的结果为false,就不再执行后面的表达式,效率较高。
System.out.println(a % 2 == 0 && a > 10);
//即使条件表达式中,前面的结果为false,依然会执行后面的表达式,效率较低。
System.out.println(a % 2 == 0 & a > 10);
//a是一个奇数,或是否小于15
//短路或:如果条件表达式中,前面的结果为false,就不再执行后面的表达式,效率较高。
System.out.println(a % 2 != 0 || a < 15);
//即使条件表达式中,前面的结果为false,依然会执行后面的表达式,效率较低。
System.out.println(a % 2 != 0 | a < 15);
//a是否是一个奇数?
System.out.println(!(a % 2 == 0));
//&、|的用法
int b = 10;
int c = 12;
boolean flag = b > c & b== 10;
System.out.println(flag);
}
}
对于上述代码中的逻辑运算符,壹哥再给大家细说一下,我们要特别注意“短路与”和“短路或”的概念:
- &&:逻辑与(短路与)。所有的结果为true,最终的结果才是true。&&属于短路与:逻辑与遵守短路求值的规则,即表达式1为假,表达式2就不再执行。即如果左边的表达式为真,右边的表达式就会执行;如果左边为假,右边不执行。
- ||:逻辑或(短路或)。所有的结果只要有一个为true,最终结果就是true。||属于短路或:遵守或也遵守短路求值的规则,即表达式1为真,表达式2就不在执行,否则就执行表达式2。
- !: 逻辑非。对结果进行取反。
- &:按位与。无论条件表达式的结果如何,都会执行完整个表达式,所在无论左边的表达式是真假,右边的表达式都要执行。
- |:按位或。无论条件表达式的结果如何,都会执行完整个表达式。无论左边的表达式是真假,右边的表达式都要执行。
bilibili html5 player
我们知道,对任何编程语言而言,最终的操作都是用二进制表示,因为计算机的底层只认识二进制。而八进制、十进制或者十六进制,都是为了让开发人员方便开发而创立的。在Java中,也可以根据数的进制进行运算,这就需要位运算符的参与了。常用的位运算符有如下几个:
& | ^ ~ << >> >>>
注意:& 和 | 既是位运算符,也可以进行逻辑运算。
接下来我们通过一个案例来演示位运算符该如何使用。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//位运算符
//按位与&
System.out.println(18 & 23);
//按位或|
System.out.println(16 | 37);
//按位亦或
System.out.println(13 ^ 34);
//按位取反
System.out.println(~14);
System.out.println(~-18);
//左移 <<
System.out.println(18 << 2);
//右移 >>
System.out.println(23 >> 2);
System.out.println(-18 >> 2);
//无符号右移 >>>
System.out.println(-23 >>> 2);
}
}
针对上述代码,壹哥给大家解释一下:
按位与&的特点:相同数位都是1,最终的结果才是1。基本规则如下:
0 & 0 = 0; 0 & 1 = 0; 1 & 0 = 0; 1 & 1 = 1;
按位或|的特点:只要相同数位上有1,结果就是1。
按位亦或的特点:相同数位相同为0,不同为1。
按位取反的特点:将每一位上的数字取反。结论:数字+1取反。
左移<<的特点:将二进制数位整体向左移动N位,低位补0。
右移>>的特点:将二进制数位整体向右移动N位。如果是正数补0,负数补1。
无符号右移>>>的特点:将二进制数位整体向右移动N位。高位补0
PS:关于进制转换、原码、反码、补码等内容,壹哥会在后面的文章中专门讲解!
bilibili html5 player
条件运算符,又叫做三目运算符,目前在 Java 中只有一个三目运算符 ? :
三目运算的语法格式如下:
布尔表达式 ? 表达式1 : 表达式2
很多时候,三目运算都是 if 和 else 的简写。
/**
* @author 一一哥Sun
* QQ:2312119590
* CSDN、掘金、知乎找我哦
*/
public class TypeDemo04 {
public static void main(String[] args) {
//条件表达式,三目运算符
//判断年龄,如果大于18岁,输出成年人,否则输出未成年人
int age = 70;
String s = age > 18 ? "成年人" : "未成年人";
System.out.println(s);
//a和b比较,输出较大的数字
int a = 10;
int b = 20;
int num = a > b ? a : b;
System.out.println(num);
//三目运算符嵌套使用
//判断年龄。如果大于18岁,输出成年人;但如果大于60岁,输出老年人,否则输出未成年人
String s1 = age > 18 ? age > 60 ? "老年人" : "成年人" : "未成年人";
System.out.println(s1);
}
}
三目运算符虽然可以嵌套使用,但我们在开发时尽量不要这么使用,这样的代码可读性很差。
bilibili html5 player
在Java中还有一个类型比较运算符instance of
,用于对Java的对象类型进行比较,可以判断定义的变量是否属于某个类,该类可以是(接口、抽象类)。语法格式如下:
boolean = 变量 instanceof 类
因为目前我们还没有学习Java面向对象的内容,所以这里我们先做个了解,知道有这么一个符号就可以了。后面壹哥会在讲面向对象时,再单独对该符号的使用进行讲解。
----------------------------------------------正片已结束,来根事后烟--------------------------------------------------
至此,壹哥就把Java里的各种常见运算符给大家讲解完毕了,现在你学会了吗?其实这些运算符记忆起来并不复杂,算术运算符的含义和使用与数学里的一样,这根本就不用单独记忆。我们只需要去记一些较为特殊的运算符用法和特点,比如三目运算符、逻辑运算符、位运算符等。
在下一篇文章中,我们会继续学习新的知识点,请大家继续保持高昂的学习劲头哦。另外如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。
java中37.2%10
的运算结果是多少?评论区告诉我吧
此处为语雀投票卡片,点击链接查看:14从零开始学Java14之Java中都有哪些运算符? · 语雀
如何高效地计算出2的幂次方?评论区给出你的实现思路