共计 18534 个字符,预计需要花费 47 分钟才能阅读完成。
你好,欢送回来,HAKUNA MATATA!!!
提到运算,你可能会立刻想到加、减、乘、除四则运算以及“九九乘法表”。想当年背诵“九九乘法表”,那几乎是一场噩梦啊!时隔多年,心中仍然隐隐作痛。不过,当初学习应用编程语言来进行运算,要比咱们本人用公式和“九九乘法表”高效的多,而且,也容易得多,因为真正的运算过程都交给机器解决,咱们只须要提供数据和计算规定就行了。
紧接着上次课程的内容,当初咱们学习在 Java 语言中如何进行数据的运算。怀揣着孩子一样的好奇,看看 Java 是怎么把数据一步一步运算出后果的。
以下是这篇文章的次要知识点:
- 十八般武艺:Java 中的运算符
- 算术运算:先学会舞刀弄枪
- 赋值运算:给技能加个点
- 比拟运算:是骡子是马,拉进去遛遛
- 逻辑运算:谁是谁非,总要有个说法
- 三目运算:抉择艰难症的终极答案
第一关 十八般武艺:Java 中的运算符
领有程序思维的第一步,就是要学会用计算机、或者说编写程序帮咱们解决数据,而不是咱们本人入手。Java 语言中有很多进行数据运算的形式,就如后面所说,包含但不限于:算术运算、比拟运算、逻辑运算、赋值运算、三目运算等。每一种运算形式,又都蕴含了很多的运算符,我把这些运算符形象的称为“十八般武艺”,学习 Java 中的运算,就是学习这些运算符的应用,也就是修炼这“十八般武艺”的过程。
运算符,顾名思义,就是对数据(常量和变量)进行运算的符号。咱们把数据用运算符连接起来,就形成了能够进行运算的表达式。比方 1 + 2
、3 * 4
等等。看看这行代码:
public class Test{public static void main(String[] args) {
int number = 1 + 2; // 应用加号(+)将常量 1 和 2 连接起来,形成了一个加法表达式,并把运算后果赋值给变量 number
System.out.println(number); // 输入 number 的值
}
}
下面的式子就是应用运算符加号(+)将常量 1
和 2
连接起来,形成了一个加法表达式,并把运算后果赋值给变量 number
,不出意外的话,打印后果应该是:
3
事实上,参加运算的数据可能会有很多,也有可能是变量、常量等混合在一起进行运算,比方(接下面代码):
public class Test{public static void main(String[] args) {
int number = 1 + 2; // 应用加号(+)将常量 1 和 2 连接起来,形成了一个加法表达式,并把运算后果赋值给变量 number
System.out.println(number); // 输入 number 的值
int count = number + 10; // 变量和常量同时参加运算
System.out.println(count); // 输入计算结果
}
}
打印后果:
13
除此之外,运算的形式也有很多,加法、减法、取余(取模)、比拟运算等等,但它们都有一个独特的特点:每个表达式都会有一个运算后果。咱们依据表达式运算后果的数据类型,将表达式的类型进行演绎分类,比方:
整型表达式:运算后果为整数。比方:
1 + 2
、10 * 20
、5 - 3
,它们的运算后果都是整数浮点型表达式:运算后果为浮点数。比方:
3.14 * 2
、0.618 + 0.382
、3.0 / 1
,它们的运算后果都是浮点数布尔型表达式:运算后果为布尔类型的值。比方:
2 > 1
、(20-10) < 15
,它们的运算后果都是布尔型:要么 true、要么 false。
练好了运算符、表达式的基本功,当初,咱们能够开始学习真正的武艺了。
第二关 算术运算(上):学会舞刀弄枪
先来几个简略的招式,好好温习咱们小学期间的算术运算。Java 中的算术运算符【大略、兴许】有七种:
后面四个运算符还算常见:+
、-
、*
、/
,尽管乘号(*)和除号(/)跟咱们以前见到的长得不一样,但并不难理解。百分号(%)在这里是“取余”、“取模”的意思,也就是说,应用百分号(%)能够失去数字 7 除以 3 之后的余数:1。而 ++
和 --
就比拟生疏了,它们别离代表数据“自增 1”和“自减 1”,这种运算是咱们以前没见过的,接下来,我手把手教你每个招式——运算符的用法。
2.1 加、减、乘、除
先学会舞刀弄枪——四则运算的用法,上代码:
public class Test{public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
int num3 = 5;
int num4 = 10;
// 1. 加法运算
int add = num1 + num2;
// 2. 减法运算
int subtract = num2 - num1;
// 3. 乘法运算
int multiply = num2 * num3;
// 4. 除法运算
int divide = num4 / num3;
// 别离输入运算后果
System.out.println(add); // 输入加法计算结果
System.out.println(subtract); // 输入减法计算结果
System.out.println(multiply); // 输入乘法计算结果
System.out.println(divide); // 输入除法计算结果
}
}
输入后果:
7
1
20
2
运算后果齐全没有新意。如果你把下面的数据类型换成其它类型的整数,后果也不会有什么意外——如果不小心翻车,请点击传送门。然而如果换成浮点数,可能会遇到惊喜——Java 中的浮点数运算不够准确,快去试一试,看你能不能找到彩蛋!
除法运算有个细节要留神:如果相除的两个数进行运算,除不尽怎么办?猜测一下,上面这个行代码会失去什么后果:
System.out.println(7 / 3); // 即 7 / 3,后果是什么,2.333... 还是 2,还是 1
看后果:
public class Test{public static void main(String[] args) {System.out.println(7 / 3);
}
}
后果竟然是 2!为什么会这样?
切记一点:除法运算符(/),失去两个数据相除的 商,在 Java 语言中,整数除以整数后果还是整数,如果除不尽,会舍弃余数。也就是说,7 / 3 的商是 2,余数为 1,因为参加运算的被除数、除数都是整数(int
类型),所以计算结果还是整数,舍弃了余数局部,后果是 2。
是不是有一种豁然开朗的感觉。这是 Java 中的运算与咱们以前的认知第一个不一样的中央。
考一考:算术运算符
上面代码的运算后果是什么?
public class Test{public static void main(String[] args) {
int int1 = 10;
long lon1 = 20;
System.out.println(lon1 + int1 * (int1 + lon1) / lon1);
}
}
A. 30
B. 45
C. 35
D. 300
答案:C
解析:仍然遵循这样的规定——“先乘除后加减,有括号先算括号外面的”,所以答案是 35
2.2 取模、自增(++)和自减(–)
再教你三个进阶招式(%、++、–):
public class Test{public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
int num3 = 5;
int num4 = 10;
int remainder = num3 % num1; // 取模 / 取余运算,5 对 3 取模,后果是?System.out.println(remainder); // 输入取模运算后果
num2++; // num2 自增 1
num4--; // num4 自减 1
System.out.println(num2); // 输入自增之后的运算后果
System.out.println(num4); // 输入自减之后的运算后果
}
}
输入后果:
2
5
9
百分号(%)是取模运算,也叫取余运算,是除法运算的一种扩大,只不过除法运算失去的后果是商,而取模运算失去的后果是余数。如果两个数进行取模运算,后果是 0,意味着什么?没错,这就是整除的成果,所以,取模运算(%)能够用来判断两个数是否可能整除,也就是说,被除数是除数的倍数。
加加(++)和减减(–)运算是让 变量 进行自增或自减。这里要留神,不能将这两个运算符间接应用到常量上,比方上面的代码是谬误的:
1++; // 不容许常量自增或自减
思考一下,为什么?那是因为常量的概念,规定了它不可能被批改,所以,如果你想要取得 2,那么间接应用字面值常量 2 就行了,齐全不须要应用另一个常量进行运算。还有个细节,下面的代码,也能够把 ++
和 --
放到变量的后面,这样的运算后果是一样的(放在变量前、后的代码不能同时存在,否则数据会进行两次运算哦):
来,咱们试试把 ++ 和 – 写到后面
++num2; // num2 自增 1
--num4; // num4 自减 1
public class Test{public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
int num3 = 5;
int num4 = 10;
int remainder = num3 % num1; // 取模 / 取余运算,5 对 3 取模,后果是?System.out.println(remainder); // 输入取模运算后果
// num2++; // num2 自增 1
// num4--; // num4 自减 1
++num2; // num2 自增 1
--num4; // num4 自减 1
System.out.println(num2); // 输入自增之后的运算后果
System.out.println(num4); // 输入自减之后的运算后果
}
}
输入后果没有变动:
5
9
当然,加加(++)和减减(–)也能够像别的运算符那样,把后果赋值给一个新的变量,就像这样:
public class Test{public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
int num3 = 5;
int num4 = 10;
int num5 = num2++; // 猜测:num2 自增 1,而后赋值给新变量 num5
int num6 = num4--; // 猜测:num4 自减 1,而后赋值给新变量 num6
System.out.println(num5); // 输入自增之后的运算后果
System.out.println(num6); // 输入自减之后的运算后果
}
}
输入后果:
4
10
咦,怎么还是原来的值?难道是没有产生运算?
看来咱们的猜测不正确,原来
int num5 = num2++; // 论断:num2 先赋值给新变量 num5,而后才进行自增运算
int num6 = num4--; // 论断:num4 先赋值给新变量 num6,而后才进行自减运算
我把加加(++)和减减(–)放到变量后面试试:
public class Test{public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
int num3 = 5;
int num4 = 10;
// int num5 = num2++; // 论断:num2 先赋值给新变量 num5,而后才进行自增运算
// int num6 = num4--; // 论断:num4 先赋值给新变量 num6,而后才进行自减运算
int num5 = ++num2; // 猜测:num2 自增 1,而后赋值给新变量 num5
int num6 = --num4; // 猜测:num4 自减 1,而后赋值给新变量 num6
System.out.println(num5); // 输入自增之后的运算后果
System.out.println(num6); // 输入自减之后的运算后果
}
}
输入后果:
5
9
终于变成正确答案了,吓得我长舒了一口气。。。
int num5 = ++num2; // 论断:num2 自增 1,而后赋值给新变量 num5
int num6 = --num4; // 论断:num4 自减 1,而后赋值给新变量 num6
然而,这是为什么呢?加加(++)和减减(–)放到变量前和放到变量后为什么后果不一样,到底数据有没有进行运算呢?分析一下这两招:
- 独自应用:放在变量前或后后果一样
- 参加其它运算:
在变量前,先自增(自减),再进行其它运算
在变量后,先以原值进行其它运算,再自增(自减)
所以,第一次把 ++
和 --
放在变量后,是把变量原来的值赋值给新变量,而自增(或自减)的值被抛弃了,因而打印的是原来的值;第二次把 ++
和 --
放在变量前,是把运算之后的值赋值给新变量,因而打印的是计算之后的数据,这就是加加(++)和减减(–)这两个运算符的底层原理。++
和 --
是一种非凡的运算,这是再一次不同于咱们以往认知的一个中央。
来,放在一起比拟一下:
public class Test{public static void main(String[] args) {
int num1 = 3;
int num2 = 4;
int num3 = 5;
int num4 = 10;
int remainder = num3 % num1; // 取模 / 取余运算,5 对 3 取模,后果是?System.out.println(remainder); // 输入取模运算后果
// num2++; // num2 自增 1
// num4--; // num4 自减 1
++num2; // num2 自增 1
--num4; // num4 自减 1
System.out.println(num2); // 输入自增之后的运算后果
System.out.println(num4); // 输入自减之后的运算后果
// int num5 = num2++; // num2 赋值给新变量 num5,而后自增 1
// int num6 = num4--; // num4 赋值给新变量 num6,而后自减 1
int num5 = ++num2; // num2 自增 1,而后赋值给新变量 num5
int num6 = --num4; // num4 自减 1,而后赋值给新变量 num6
System.out.println(num5); // 输入自增之后的运算后果
System.out.println(num6); // 输入自减之后的运算后果
}
}
考一考:取模运算
如何获取一个三位数的十位?比方:324。
答案:
public class Test{public static void main(String[] args) {
int number = 324;
int noGeWei = number / 10; // 除以 10,商 32(Java 中整数除以整数还是整数,舍弃了余数)int shiWei = noGeWei % 10; // 再对 10 取余,商 3,余数为 2,即十位
System.out.println("324 的十位数是:" + shiWei);
}
}
考一考:自增(++)、自减(–)运算
上面代码的运算后果是什么?
public class Test{public static void main(String[] args) {
int a = 5;
a++;
int b = ++a;
System.out.println("a:" + a);
System.out.println("b:" + b);
}
}
A. 5,5
B. 5,6
C. 6,6
D. 6,7
E. 7,6
F. 7,7
答案:F
解析:变量 a
自增了两次,所以是 7
变量 b
是在变量 a
第二次自增之后被赋值的,因为加加(++)在变量前(第四行代码),所以 b
也是 7
第三关 算术运算(下):学会舞文弄墨
3.1 字符型(char)的算术运算
根底操作太简略,敢不敢玩点高级的?
来一波神奇操作:
int ch = 'a' + '0'; // 字符型数据进行运算,后果是?
先不焦急看后果,你能不能看懂下面的代码?想要弄明确下面的代码,必须解决上面两个问题:
- 为什么字符型数据能够进行算术运算?
- 字符型数据是如何进行运算的?
上次课咱们提到过,字符数据类型(char)代表世界上所有国家和地区的文字、数字、特殊符号等,而这些字符数据,在计算机中是如何存储的呢?其实,计算机中所有数据的存储和运算都是以二进制模式进行的。也就是说,计算机会把所有的数据都转化成数值,而后将该数值以二进制的模式存储在磁盘上,也因而,进行运算的过程,是以二进制的模式进行的。你想晓得二进制数据的运算过程?想得美,我是不会教的。回到下面的问题,你须要晓得的是:
- 每个字符型数据在计算机中都是一个数值,所以它能够进行算术运算。
- 既然字符型数据是数值,就把它对应的数值拿过去进行运算好了。
那么问题来了,每个字符对应的数值是多少呢?秀一波操作:
public class Test{public static void main(String[] args) {System.out.println('a' + 0); // 任意数值 + 0 = 数值自身
System.out.println('0' * 1); // 任意数值 * 1 = 数值自身
}
}
算术运算符的加法和乘法,都有非凡技巧:任意数值 + 0 = 数值自身;任意数值 * 1 = 数值自身。所以,下面的输入后果是:
97
48
也就是说,字符型字面值常量 'a'
和 '0'
在计算机中存储的数值别离是 97 和 48。所以,这两个字符相加的后果是:
145
这就是字符型(char)的算术运算,归根结底,就是把 char
类型的字符转成了 int
型的数值进行运算的。
如果有个表,能随时查阅常见的字符和对应的数值就好了!
美国信息替换规范码对照表(ASCII 码对照表,读音“阿斯 key”),外面记录了常见字符和对应数值的对照关系,拿走不谢:
太多记不住?没关系,罕用的字符 'a' - 'z'
、'A' - 'Z'
、'0' - '9'
对应的数值都是间断的,只记住它们的开始和结尾字符对应的数值就行了:
怎么样老铁,这服务还算到位不?
到底为止,Java 语言的八种根本数据类型,只剩下布尔(boolean)类型没有波及。你认为要讲 boolean
类型了?偏不!因为:
Java 语言中,布尔类型(boolean)不参加算术运算。
咳咳。
3.2 数据类型转换
欢送来到传送门。我是机器人砰砰,有何批示?
“代码翻车了,都是你教的,你本人看:
”
“不就是个编译谬误嘛,不怕不怕哈!
咱们来剖析一下错误信息:
Incompatible types. // 不兼容的类型
Required: byte // 须要 byte 类型
Found: int // 却找到 int 类型
看起来如同是类型不匹配的问题:程序须要一个 byte
类型,却失去了一个 int
类型。”
“可我的代码里基本没有用 int
类型啊,这是怎么肥四?”
“是这样的,byte
、short
这两种类型在运算的时候,会先把它们转成 int
,而后再进行运算,运算后果也是 int
,int
类型就是这么来的。”
“那当初怎么办?”
“须要把运算后果进行数据类型转换。就像这样:
// 强制类型转换:把 b2 - b1 的后果进行转换,从 int 类型转成 byte 类型
byte b3 = (byte)(b2 - b1);
”
这就是 强制类型转换 操作。把 b2 – b1 的 后果 进行转换,从 int
类型转成 byte
类型。因为 int
类型的范畴大于 byte
类型,所以叫“强制类型转换”,也叫“显式类型转换”;反过来,如果是从 byte
类型转成 int
类型,叫“主动类型转换”,也叫“隐式类型转换”,因为这个过程是默认产生的。比方上面的代码,就是隐式类型转换:
byte x = 3;
int y = x; // 将 byte 类型的变量 x 赋值给 int 类型的变量 y,隐式类型转换
隐式转换是主动产生的,不须要咱们进行任何操作。Java 语言中的八种根本数据类型,除了布尔类型(boolean)不参加算术运算之外,其它的七种类型主动转换的程序是这样的:
之所以是这样的程序,是因为它们各自的示意范畴不同,从小到大顺次是:byte
、short
、char
、int
、long
、float
、double
。小类型与大类型一起运算,除了 byte
、short
、char
这三种类型或默认晋升成 int
类型进行运算之外,其它状况都会主动将小类型晋升成大类型,而后再进行运算,运算后果也是大类型。看看这行代码:
public class Test{public static void main(String[] args) {System.out.println(7 / 3.0); // 除法运算,被除数是整数,除数是浮点数,后果是几?什么数据类型?}
}
输入:
2.3333333333333335
后果是一个有限循环小数,这个后果很有意思:第一:后果是浮点数;第二,后果不是 2,跟后面遇到的状况不同;第三,后果最初一位如果是四舍五入的值,应该是 3 而不是 5。解决这三个问题:第一,数字 7 默认是 int
类型,3.0 是 double
类型,依据下面的主动类型转换图示,运算过程会将 int
类型的 7 转成 double
类型,所以后果也是 double
类型;第二,既然运算后果是 double
类型,那么除不尽的局部,也就是小数点前面的值,不会被舍弃,所以后果不是 2;第三,在 Java 语言中,浮点数参加运算,很有可能会造成精度的损失,这是 Java 语言浮点数运算的一个缺点,所以小数点最初的数值是不可预知的。
除此之外,强制类型转换也并非是万能的,甚至,有的时候可能会产生意想不到的后果。比方这段代码:
public class Test{public static void main(String[] args) {
int first = 131;
int second = 1;
byte bys = (byte)(first - second); // 将两个 int 类型的值进行运算,而后将后果强转为小类型 byte
System.out.println(bys); // 输入后果
}
}
输入:
-126
怎么会这样?难道不应该是 130 吗,竟然还是个正数?
那是因为,byte
类型只能示意 -128 到 127
之间的数据,超出这个范畴的数据,只能持续从 -128 算起,所以,将 int
类型的 130 转成 byte
类型的数据运算过程是这样的:
127 + 1 = -128 // 130 = 127 + 3
-128 + 1 = -127
-127 + 1 = -126 // 最终后果是 -126。
最终后果是 -126。
多种不同的数据类型的益处在于,能够依据内存和计算量的大小进行抉择,毛病也很显著,不同类型的数据进行运算时,有可能产生重大的兼容性问题。Java 是一种强类型的语言,这意味着两点:一,每一种数据都必须有十分清晰的类型;二、不同类型的数据进行运算,必须保障彼此的兼容性。不同类型的数据之间可能会进行运算,而这些数据取值范畴不同,存储形式不同,间接进行运算可能会造成数据损失,所以 当且仅当大类型数据能够转换为小类型数据(而不会产生精度损失)时,才进行转换。对于数据类型转换,你须要晓得的:
强制类型转换操作是要把运算“后果”转成小类型,而不是只转换变量,这是操作中容易呈现的谬误,为此,进行强转时肯定要留神格局:
小类型 变量名 = (小类型)大类型数据;
参考残缺代码:
public class Test{public static void main(String[] args) {
byte b1 = 3;
byte b2 = 4;
// byte b3 = b2 - b1; // 报错
// 强制类型转换:把 b2 - b1 的后果进行转换,从 int 类型转成 byte 类型
byte b3 = (byte)(b2 - b1);
System.out.println(b3); // 输入后果
/* 隐式转换 */
byte x = 3;
int y = x; // 将 byte 类型的变量 x 赋值给 int 类型的变量 y,隐式类型转换
/* 多数据类型参加运算,后果是几?什么数据类型?*/
System.out.println(7 / 3.0); // 除法运算,被除数是整数,除数是浮点数,后果是 2.3333333333333335
/* 数据太大,小类型接管不了 */
int first = 131;
int second = 1;
byte bys = (byte)(first - second); // 将两个 int 类型的值进行运算,而后将后果强转为小类型 byte
System.out.println(bys); // 输入后果:-126
}
}
考一考:强制类型转换
上面的代码运算后果是什么?
public class Test{public static void main(String[] args) {
short s1 = 20;
short s2 = 30;
short s3 = (short)s2 - s1;
System.out.println(s3);
}
}
A. 20
B. 30
C. 10
D. 编译谬误
答案:D
解析:强转操作仅仅对变量 s2
无效,所以 (short)s2 - s1
的后果还是int
类型,间接赋值给short
类型的 s3
,编译报错
3.3 加号(+)的骚操作
加号(+)除了作为算术运算符之外,还有一个骚气蓬勃的技能,在开发中应用频率十分高,那就是作为字符串连接符来应用:
public class Test{public static void main(String[] args) {
int age = 10;
String desc = "我的年龄是";
System.out.println(desc + age); // 间接应用加号,将字符串和数值连接起来
}
}
输入后果:
我的年龄是 10
这里的加号起到字符串拼接的作用,所以,它当初是字符串连接符。除了用在两个变量两头,常量也是通吃:
public class Test{public static void main(String[] args) {System.out.println("我是一个" + "小小的石头。"); // 间接应用加号,将两个字符串连接起来
}
}
输入后果:
我是一个小小的石头。
可问题是,为什么后面的算术运算能够失去数值的后果,到这里却是字符串了呢?
这就是加号(+)的骚操作了。编译器会自动识别加号(+)两边的数据类型,如果有任意一个数据是字符串类型,那么此时加号(+)就是字符串连接符,否则就是算术运算符,这就是本源。
考一考:加号(+)的非凡用法
上面代码的执行后果是什么?
public class Test{public static void main(String[] args) {
int a = 3;
int b = 5;
char c = '1';
String s = "A";
System.out.println(a - b + c + s + c + b);
}
}
答案:47A15
解析:
第一个操作:a - b
,算术运算,后果是 -2;
第二个操作:-2 + c
,算术运算,获取字符 ‘1’ 的 ASCII 码值 49,后果是 47;
第三个操作:47 + s
,字符串拼接,所以是 “47A”;
第四个操作:"47A" + c
,字符串拼接,”47A1″;
第五个操作:"47A1" + b
,字符串拼接,最终后果是 47A15
3.4 算术运算小结
对算术运算符进行小结。
/:除法运算符,失去两个数据相除的 商。
特点:Java 中整数除以整数后果还是整数。
%:取模(取余)运算,失去两个数据相除的 余数。
特点:能够用来判断两个数是否可能整除。
- 布尔类型(boolean)不参加算术运算。
加号两边是数值型数据时,进行加法运算
‘a’、‘0’等字符型数据参加运算时,用该字符在计算机中所示意的数值进行运算
- 加号两边有任意一边是字符串时,进行字符串的拼接。
++ 和 —:自增 1 / 自减 1
独自应用:
放在变量前或后后果一样
- 参加运算:
在变量前,先自增(自减),再进行其它运算
在变量后,先以原值进行其它运算,再自增(自减)
- 当且仅当大类型数据能够转换为小类型数据(而不会产生精度损失)时,才进行转换。留神强转的固定格局。
第四关 赋值运算:给技能加个点
在学习变量之前,咱们可能并不常见“赋值”这种说法,而且,咱们也不会把等号(=)说成是赋值符号。没错,这个词应该是计算机的专有词汇。在编程语言里,咱们把等号(=)称作“赋值符号”,它的含意是:把左边的数据赋给右边的变量。赋值的过程就像玩游戏时给技能加点一样,原来的技能没有点亮,加点(被赋值)之后就能够应用这个技能了;原来的技能等级太低,也能够通过加点(赋一个更大的值)降级技能。赋值符号不止一种,最常见的就是由根本赋值运算符(=)联合算术运算符,这样就失去一些扩大运算符,比方:
根本赋值运算符的用法,我就不啰嗦了。来看看扩大赋值运算符这几个招式怎么玩。
public class Test{public static void main(String[] args) {
int num = 10;
num += 10; // 应用 += 赋值运算符
System.out.println(num); // 输入运算后的后果
}
}
输入:
20
很显著,通过加等赋值运算符(+=)的运算,变量 num
的值变成了 20,这是怎么回事呢?
其实很简略,扩大赋值运算符相当于算术运算符与赋值运算符的合体,所以这些运算符既有算术运算符的性能,又有赋值运算符的性能,也就是说,上面的两行代码的成果的一样的:
// 这两行代码的成果一样
num += 10;
num = num + 10;
说白了,扩大赋值运算符无非就是一种简写模式。
难道扩大赋值运算符的益处仅仅如此吗?当然不是。再看一段代码:
public class Test{public static void main(String[] args) {
short s = 1;
// s = s + 1; // 报错
s += 1; // 相当于 s = (short)(s + 1);
System.out.println("s:" + s); // s:2
}
}
通过后面的学习,咱们晓得,short
类型的变量 s
如果间接加上常量 1,会变成 int
类型,所以像 s = s + 1;
这样的代码必定会报错,然而 s += 1;
却没有任何问题,这阐明了加等赋值运算符(+=)是曾经进行了强制类型转换的动作的,这就是扩大赋值运算符的益处:省略了强制类型转换的操作。
当然,其它的扩大赋值运算符的特点是一样的,这里就不赘述了。
赋值运算符很好了解,你当前勤加练习就能够了!
第三关 比拟运算:是骡子是马,拉进去遛遛
小的时候,常听父母说:你是哥哥 / 姐姐,比弟弟妹妹们大,要让着点弟弟妹妹。小时候比年龄、比个头,而后比学习成绩;长大了比工资,比男 / 女朋友,再而后比谁的房子大,谁的车子好;人到中年就开始比孩子,老了之后比儿子、孙子。唉,人这毕生,比赢了就得意,比输了就得志。比拟无处不在,真是让人又恨又爱。
比拟运算符又叫关系运算符,顾名思义,就是用来比拟两个值之间的大小关系的。比方上面这段代码:
public class Test{public static void main(String[] args) {System.out.println(5 > 3); // 5 和 3 比拟,5 大于 3 成立吗
}
}
输入后果:
true
很显著,5 大于 3 是成立的,所以后果是 true。反之,如果不成立,后果就是 false。所以,无论谁大谁小,谁胜谁败,比拟的后果只有两种状况:true
和 false
。也就是说,比拟 / 关系运算符的运算后果都是布尔(boolean)类型,要么是 true,要么是 false。常见的关系运算符:
在 Java 中比拟两个数据的大小关系,应用比拟运算符(或者说关系运算符),这里要留神,比拟两个数据是否相等,用的是双等号(==),因为在 Java 中,一个等号(=)的意思是“赋值”;而“不等于”符号是一个感叹号加一个等号(!=),肯定要留神它们的写法。来看一段代码:
public class Test{public static void main(String[] args) {
// 定义三个变量
int a = 10;
int b = 20;
int c = 10;
// ==: 等于
System.out.println(a == b); // false
System.out.println(a == c); // true
System.out.println("-----------------------------");
// !=: 不等于
System.out.println(a != b); // true
System.out.println(a != c); // false
System.out.println("-----------------------------");
// >: 大于
System.out.println(a > b); // false
System.out.println(a > c); // false
System.out.println("-----------------------------");
// >=: 大于等于
System.out.println(a >= b); // false
System.out.println(a >= c); // true
System.out.println("-----------------------------");
}
}
比拟运算符和赋值运算一样好了解。惟一值得注意的点,就是双等号(==)和单等号(=)的区别:
public class Test{public static void main(String[] args) {
// 定义三个变量
int a = 10;
int b = 20;
int c = 10;
// 留神: == 是判断是否相等, = 是赋值的意思
System.out.println(a == b); // 判断变量 a 和变量 b 的值是否相等, false
System.out.println(a = b); // 将变量 b 的值赋值给变量 a, 而后打印后果, 20
}
}
双等号是比拟相等,单等号是赋值的意思,切记。
第四关 逻辑运算:谁是谁非,总要有个说法
一提起“逻辑运算”,咱们往往想到的是简单的运算过程,其实不然,当初介绍的逻辑运算非常简单:用于判断“并且”、“或者”、“除非”等逻辑关系。比照后面介绍的比拟运算符,逻辑运算和比拟运算如同都须要判断,所以它们的运算后果类型是统一的:boolean
类型,逻辑运算绝对于比拟运算更简单的一点是,逻辑运算比拟多个后果之间的逻辑,而比拟运算个别只须要比拟两个数据之间的一个后果。有点绕,举个栗子:
public class Test{public static void main(String[] args) {
int a = 10, b = 20, c = 30; // 申明三个变量
System.out.println(a > b); // 比拟运算,比拟两个数据的大小,只有一个后果
System.out.println(a > b && b > c); // 逻辑运算,有两个比拟后果参加逻辑与(&&)运算
}
}
输入:
false
false
两次输入都是 false。也就是说,比拟运算和逻辑运算的后果,都是 boolean
类型,只不过 逻辑运算符两端个别连贯值为布尔类型的关系表达式,而比拟运算两端连贯的是数据。常见的逻辑运算符:
下面的代码应用了逻辑运算符:&&(逻辑与,并且)。它的含意是,当两边的表达式后果同时为 true
时,逻辑运算的后果才是 true
,反过来说,只有任意一边的后果为 false
,那么整个逻辑运算的后果就是 false
。相应的,逻辑或(||)的含意是:只有有任意一边是 true
,逻辑运算的后果就是 true
。逻辑非(!)示意否定,它的含意是:如果原来的后果为 true
,加上 !
后果就是 false
,反之,如果原来的后果为 false
,加上 !
则为 true
。
韦小宝喜爱娶媳妇儿,他的要求有三个:第一,是女性;第二,要好看;第三,要身材好。来一段代码:
public class Test{public static void main(String[] args) {
/*
案例: 韦小宝找媳妇儿
要求有三个:第一,是女性;第二,要模样难看;第三,要身材好。*/
int sex = -1; // 性别。-1- 女,1- 男
int rongMao = 1; // 模样。0- 不难看,>0 难看
int shenCai = 0; // 身材。0- 身材不好,1- 身材好
// 刚开始眼光比拟高, 要求既要长得难看,还要身材好
System.out.println(sex == -1); // 性别是女性
System.out.println(rongMao > 0 && shenCai == 1); // 模样难看,身材好
System.out.println("---------------------");
// 韦小宝发现那样的媳妇儿不好找, 于是升高了择偶规范, 只有长得难看, 或者身材好就行
System.out.println(sex == -1); // 性别是女性
System.out.println(rongMao > 0 || shenCai == 1);
System.out.println("---------------------");
// 韦小宝发现那样的媳妇儿不好找, 于是升高了择偶规范, 只有不是男的就行
System.out.println(sex != 1); // 性别不是男
System.out.println("---------------------");
}
}
输入后果:
true
false
---------------------
true
true
---------------------
true
---------------------
找个媳妇儿不容易,且行且珍惜。
这里再提一下逻辑非(!)的应用。它示意否定,如果原来的值是 false
,加上 !
就变成了 true
,也就是说:双重否定示意必定。当代码里有多个逻辑非(!)同时呈现时,能够间接把偶数个逻辑非(!)间接去掉,因为后果不会扭转:
public class Test{public static void main(String[] args) {System.out.println(!!!!!!true); // 6 个逻辑非,后果还是 true
}
}
输入:
true
逻辑与(&&)和逻辑或(||)别离有一个双胞胎兄弟,它们也是逻辑与和逻辑或,然而它们看起来瘦骨嶙峋,如同是营养不良:
逻辑与:&
逻辑或:|
没错,咱们通常称这些逻辑运算符为:双与(&&)和单与(&);双或(||)和单或(|)。尽管这俩双胞胎兄弟看起来瘦瘦的,然而它们的性能并没有缩水。它们(单与、或)依然具备和兄长们一样的逻辑解决性能,然而区别在于,双与(&&)和双或(||)都具备“短路”的成果,而瘦兄弟们没有:
public class Test{public static void main(String[] args) {
int a = 3, b = 5, c = 4;
int d = 0;
System.out.println(a > b && (d = b) > c); // 应用双与进行逻辑运算,第一个条件不成立,第二个条件是否执行
System.out.println(d); // d 的值是几,0 还是 5?}
}
应用双与进行逻辑运算,第一个条件 a > b
是不成立的,那么第二个条件是否执行?变量 d
是否被胜利赋值成 b
的值?,看运算后果,晓得给变量 d
赋值的动作 (d = b)
并没有胜利,也就意味着,当双与(&&)后面的条件不成立(后果是 false
),前面的代码就不再执行了,这就是所谓“短路”的成果。换成单与(&)呢:
public class Test{public static void main(String[] args) {
int a = 3, b = 5, c = 4;
int d = 0;
System.out.println(a > b & (d = b) > c); // 应用单与进行逻辑运算,第一个条件不成立,第二个条件是否执行
System.out.println(d); // d 的值是几,0 还是 5?}
}
输入后果:
false
5
很显著,单与(&)没有“短路”的成果。
双或(||)执行逻辑相似:后面的条件后果为 true
,那么就意味着整个逻辑表达式肯定为 true
,所有前面的代码就不执行了;反之,后面的条件为 false
,前面依然进行判断,而单或(|)没有这样的成果。先来看双或(||)的成果:
public class Test{public static void main(String[] args) {
int a = 3, b = 5, c = 4;
int d = 0;
System.out.println(b > a || (d = b) > c); // 应用双或进行逻辑运算,第一个条件成立,第二个条件是否执行
System.out.println(d); // d 的值是几,0 还是 5?}
}
输入:
true
0
换成单或(|):
public class Test{public static void main(String[] args) {
int a = 3, b = 5, c = 4;
int d = 0;
System.out.println(b > a | (d = b) > c); // 应用双或进行逻辑运算,第一个条件成立,第二个条件是否执行
System.out.println(d); // d 的值是几,0 还是 5?}
}
输入:
true
5
总的来说:双与(&&)和单与(&)的逻辑判断能力是一样的,只不过双与(&&)有短路的成果,而单与(&)没有;双或(||)与单或(|)的情理雷同。
考一考:逻辑运算符
上面代码的输入后果是什么?
public class Test{public static void main(String[] args) {
int x, y = 0, z = 1;
boolean r1 = (x = 0) > y & (z = y) == 1;
boolean r2 = y < z || (x = 2) > (z = z +1);
System.out.println(r1 && r2);
System.out.println(x);
System.out.println(y);
System.out.println(z);
}
}
A. true; x=0; y=0; z=0
B. true; x=2; y=0; z=1
C. false; x=2; y=0; z=1
D. false; x=0; y=0; z=2
答案:C
解析:
r1 的后果:
(x = 0)
是赋值动作,此时 x = y = 0
,所以 (x = 0) > y
的后果是false
;
(z = y)
也是赋值动作,这是 z = y = 0
,所以 (z = y) == 1
的后果也是false
;
逻辑单与(&),因为两边都会执行,所以最初的后果是:x = y = z = 0
;
r1 是 false & false
,后果是 false
;
r2 的后果:
y < z
的后果是 false
;
(x = 2)
和 (z = z + 1)
都是赋值动作,所以这时,x = 2, z = 1
,双或(||)左边的表达式后果为 true
;
r2 是:false || true
,后果是true
最初的输入:r1 && r2
相当于 false && true
,后果是false
;x = 2, y = 0, z = 1
第五关 三目运算:抉择艰难症的终极答案
当你面临两难抉择时,该怎么办?当初教你终极答案:三目运算。
三目运算,又叫三元运算,即由三局部组成,格局如下:
关系表达式 ? 后果 1:后果 2
三目运算符由问号(?)和冒号(:)两个特殊符号隔开了三局部:
第一局部:关系表达式,代表了你当初遇到的问题
第二局部:后果 1,第一个可能的后果,代表了你面临的第一个抉择
第三局部:后果 2,第二个可能的后果,代表了你面临的第二个抉择
世事变化多端,与其面临抉择时慌不择路,倒不如将选择权交给后面的条件,条件满足,则抉择第一个后果,不满足则抉择第二个后果,这就是以不变应万变。所以,三目运算符的执行流程是这样的:
如果关系表达式后果为 true,运算后的后果是 后果 1
如果关系表达式后果为 false,运算后的后果是 后果 2
举个栗子,求两个整数的较大值:
public class Test{public static void main(String[] args) {
// 定义两个整数变量
int a = 100;
int b = 20;
int max = (a >= b) ? a : b ; // 通过三元运算符计算他们的较大值
System.out.println("max:" + max); // 将后果打印到管制台上
}
}
下面第三行代码的含意是:当 a >= b
这个条件成立时,较大值为 a
,否则为 b
。很显著,最初的输入后果是变量 a
的值:
100
如果有三个数据呢?很简略,三目运算符是能够嵌套的:
public class Test{public static void main(String[] args) {
// 定义两个整数变量
int a = 100;
int b = 20;
int c = 50;
int max = (a >= b) ? (a > c ? a : c) : (b > c ? b : c) ; // 通过三元运算符计算他们的最大值
System.out.println("max:" + max); // 将最大后果打印到管制台上
}
}
最大值依然是 100:
100
尽管三目运算符能够嵌套,然而代码的可读性显著变差了,所以,开发中是不倡议这样做的。你能够把它们拆开,一步一步求取最大值。
考一考:三目运算符
上面代码的运算后果是什么?
public class Test{public static void main(String[] args) {
int a = 3, b = 5;
int c;
int result = (c = b) > a ? c - a : c + a;
System.out.println(result);
}
}
A. 2
B. 5
C. 8
D. 编译谬误
答案:A
解析:
(c = b)
是赋值操作,相当于 b > a
后果是 true
;这时 a = 3,b = 5, c = 5
;
因为三目运算符的问号(?)右边后果为 true
,所以后果是 c - a
,也就是 2。而 c + a
没有执行。
总结
当初,对赋值运算符、比拟运算符、逻辑运算符、三目运算符做个总结:
赋值运算符:
1. 常见的赋值运算符:=、+=、*=、-=、/=、%=
2. 扩大赋值运算符的益处:主动强转
3. 留神:
= 示意赋值操作,不是相等
== 用来示意相等
比拟 / 关系运算符:
1. 关系运算符是用来形容两个变量的大小是否为相等关系的
2. 常见的关系运算符:>、<、==、!=、>=、<=
3. 留神:关系运算符 == 和赋值运算符 = 的区别
逻辑运算符:
1. 用于判断“并且”、“或者”、“除非”等逻辑关系的运算符
2. 逻辑运算符两端连贯关系表达式,或逻辑表达式
3. 逻辑运算符的运算后果为布尔值:true 或 false
4. 双与和双或都有短路成果,单与和单或没有
5. 偶数个逻辑非!后果不变
三目 / 三元运算符:
1. 格局:关系表达式 ? 后果 1 : 后果 2;
2. 执行流程:
关系表达式后果为 true,三元运算符后果为“后果 1”;
关系表达式后果为 false,三元运算符后果为“后果 2”;
这么多运算符,到底它们的优先级程序是怎么的呢?
一句顺口溜请好好练练~~~
单目乘除为关系,逻辑三目后赋值。
单目:单目运算符 + –(正数) ++ — 等
乘除:算数单目运算符 * / % + –
为:位移单目运算符 << >>(临时没有讲到)
关系:关系单目运算符 > < >= <= == !=
逻辑:逻辑单目运算符 && || & | ^
三目:三目单目运算符 A > B ? X : Y
后:无意义,仅仅为了凑字数
赋值:赋值 =