关于后端:Java运算比99乘法表还简单

2次阅读

共计 18534 个字符,预计需要花费 47 分钟才能阅读完成。

你好,欢送回来,HAKUNA MATATA!!!

提到运算,你可能会立刻想到加、减、乘、除四则运算以及“九九乘法表”。想当年背诵“九九乘法表”,那几乎是一场噩梦啊!时隔多年,心中仍然隐隐作痛。不过,当初学习应用编程语言来进行运算,要比咱们本人用公式和“九九乘法表”高效的多,而且,也容易得多,因为真正的运算过程都交给机器解决,咱们只须要提供数据和计算规定就行了。

紧接着上次课程的内容,当初咱们学习在 Java 语言中如何进行数据的运算。怀揣着孩子一样的好奇,看看 Java 是怎么把数据一步一步运算出后果的。

以下是这篇文章的次要知识点:

  • 十八般武艺:Java 中的运算符
  • 算术运算:先学会舞刀弄枪
  • 赋值运算:给技能加个点
  • 比拟运算:是骡子是马,拉进去遛遛
  • 逻辑运算:谁是谁非,总要有个说法
  • 三目运算:抉择艰难症的终极答案

第一关 十八般武艺:Java 中的运算符

领有程序思维的第一步,就是要学会用计算机、或者说编写程序帮咱们解决数据,而不是咱们本人入手。Java 语言中有很多进行数据运算的形式,就如后面所说,包含但不限于:算术运算、比拟运算、逻辑运算、赋值运算、三目运算等。每一种运算形式,又都蕴含了很多的运算符,我把这些运算符形象的称为“十八般武艺”,学习 Java 中的运算,就是学习这些运算符的应用,也就是修炼这“十八般武艺”的过程。

运算符,顾名思义,就是对数据(常量和变量)进行运算的符号。咱们把数据用运算符连接起来,就形成了能够进行运算的表达式。比方 1 + 23 * 4 等等。看看这行代码:

public class Test{public static void main(String[] args) {
        int number = 1 + 2; // 应用加号(+)将常量 1 和 2 连接起来,形成了一个加法表达式,并把运算后果赋值给变量 number
        System.out.println(number); // 输入 number 的值
    }
}

下面的式子就是应用运算符加号(+)将常量 12 连接起来,形成了一个加法表达式,并把运算后果赋值给变量 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 + 210 * 205 - 3,它们的运算后果都是整数

浮点型表达式:运算后果为浮点数。比方:3.14 * 20.618 + 0.3823.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'; // 字符型数据进行运算,后果是?

先不焦急看后果,你能不能看懂下面的代码?想要弄明确下面的代码,必须解决上面两个问题:

  1. 为什么字符型数据能够进行算术运算?
  2. 字符型数据是如何进行运算的?

上次课咱们提到过,字符数据类型(char)代表世界上所有国家和地区的文字、数字、特殊符号等,而这些字符数据,在计算机中是如何存储的呢?其实,计算机中所有数据的存储和运算都是以二进制模式进行的。也就是说,计算机会把所有的数据都转化成数值,而后将该数值以二进制的模式存储在磁盘上,也因而,进行运算的过程,是以二进制的模式进行的。你想晓得二进制数据的运算过程?想得美,我是不会教的。回到下面的问题,你须要晓得的是:

  1. 每个字符型数据在计算机中都是一个数值,所以它能够进行算术运算。
  2. 既然字符型数据是数值,就把它对应的数值拿过去进行运算好了。

那么问题来了,每个字符对应的数值是多少呢?秀一波操作:

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 类型啊,这是怎么肥四?”

“是这样的,byteshort 这两种类型在运算的时候,会先把它们转成 int,而后再进行运算,运算后果也是 intint 类型就是这么来的。”

“那当初怎么办?”

“须要把运算后果进行数据类型转换。就像这样:

    // 强制类型转换:把 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)不参加算术运算之外,其它的七种类型主动转换的程序是这样的:

之所以是这样的程序,是因为它们各自的示意范畴不同,从小到大顺次是:byteshortcharintlongfloatdouble。小类型与大类型一起运算,除了 byteshortchar 这三种类型或默认晋升成 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 算术运算小结

对算术运算符进行小结。

  1. /:除法运算符,失去两个数据相除的

    特点:Java 中整数除以整数后果还是整数。

  2. %:取模(取余)运算,失去两个数据相除的 余数

    特点:能够用来判断两个数是否可能整除。

  3. 布尔类型(boolean)不参加算术运算。
  4. 加号两边是数值型数据时,进行加法运算

    ‘a’、‘0’等字符型数据参加运算时,用该字符在计算机中所示意的数值进行运算

  5. 加号两边有任意一边是字符串时,进行字符串的拼接。
  6. ++ 和 —:自增 1 / 自减 1

    1. 独自应用:

      ​ 放在变量前或后后果一样

    2. 参加运算:

    ​ 在变量前,先自增(自减),再进行其它运算

    ​ 在变量后,先以原值进行其它运算,再自增(自减)

  7. 当且仅当大类型数据能够转换为小类型数据(而不会产生精度损失)时,才进行转换。留神强转的固定格局。

第四关 赋值运算:给技能加个点

在学习变量之前,咱们可能并不常见“赋值”这种说法,而且,咱们也不会把等号(=)说成是赋值符号。没错,这个词应该是计算机的专有词汇。在编程语言里,咱们把等号(=)称作“赋值符号”,它的含意是:把左边的数据赋给右边的变量。赋值的过程就像玩游戏时给技能加点一样,原来的技能没有点亮,加点(被赋值)之后就能够应用这个技能了;原来的技能等级太低,也能够通过加点(赋一个更大的值)降级技能。赋值符号不止一种,最常见的就是由根本赋值运算符(=)联合算术运算符,这样就失去一些扩大运算符,比方:

根本赋值运算符的用法,我就不啰嗦了。来看看扩大赋值运算符这几个招式怎么玩。

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。所以,无论谁大谁小,谁胜谁败,比拟的后果只有两种状况:truefalse。也就是说,比拟 / 关系运算符的运算后果都是布尔(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
后:无意义,仅仅为了凑字数
赋值:赋值 =

正文完
 0