Java SE基础知识(二)--整数的运算符

Java SE 是什么,包括哪些内容(二)?

本文内容参考自Java8标准

一、代码运行机制相关的内容:

  • 1、Java中的类型分类(“你编程时能使用的类型全部在这里了”):

    • ⑴、Java是一种静态语言 静态语言的意义在于:在Java编程过程中声明的每一个变量和每一个表达式在编译期就是已知类型,而不用在运行的时候根据实际的赋值再去判断。JavaScript中任何类型都是通过 "var"关键字进行声明,直到运行时才知道是什么类型,但是Java中为每一种类型都提供了关键字
    • ⑵、Java是一种强类型语言,因为它限制了变量以及表达式可以生成的值类型,如果超出了它所规定的类型范围,则Java编译器会报错,无法编译。同时也限制了这些值支持的操作,确定了操作的含义,以上两点的存在,非常有利于在编译时检测出错误 如果Java没有这么完备的类型体系,没有这么多明确的类型关键字,那么所有的逻辑检查,所有的错误检查,都需要在运行时进行,这显然会增加运行时负担,一但出现错误,程序必然就要停下来
      总体上看,Java中的类型分为两大类:一是基本类型,一是引用类型。
      • ①、基本类型:
        基本类型在之前(一)的时候已经说过了,总共8种,boolean类型和数值类型(整数类型[byte,char,short,int,long],浮点数类型[float,double])。
      • ②、引用类型
        引用类型总共有四种:
        1、类类型(Java是面向对象的,在Java中一切皆为对象,那么对象实际上就是类的一个一个实例,我们利用Java编程的时候,首先需要将涉及到的所有内容都抽象成一个个的类[你抽象的越详细,则编程过程会越简单],其次通过Java创建实例的机制,将这些类的实例创建出来,再次构建类实例之间的相互依赖关系,相互传递信息的通道。最后自然就形成了一个个的软件系统。)。
        2、接口类型(接口的功能特点后期博文再详述)。
        3、数组类型(数组类型的功能特点在后期博文再详述)。
        4、null(这是一个特殊的类型,实际上是一个值,但是确实有它存在的必要性)。
        分清楚了以上类型,有便于我们的记忆!
        这里还需要说明的就是Java代码运行时的两种硬件存储结构:一种叫做"堆栈"、一种叫做堆、“堆栈"最突出的特点就是:所有存储在堆栈中的东西都需要知道确切的创建时间以及销毁时间,这就极大限制了程序的灵活性(因为程序运行的时候,需要不断地通过堆栈的指针下移上移来创建新内存和回收内存),这就是为什么C和C++程序员需要绞尽脑汁去设计整个系统中所有变量以及对象实例的创建和销毁(C和C++中的变量和对象实例都是存储在堆栈中),从而避免内存的爆满,如果销毁时机不合适,还会拖累程序的运行效率。而Java的改变就在于,将对象实例存储在堆中(堆中存储的东西不需要有确切的销毁时间,它存储空间的状态与程序的运行效率无关,也不存在一个叫做"指针"的东西,就是一直存储在那里都没有关系,因为它就是一个单纯的存储空间),然后现在问题来了,我们都知道,Java是通过new关键字来创建对象实例并将对象实例存储在堆中,而程序的运行是通过操作堆栈中的内容来继续的,并没有直接操作堆,那么如果在运行的时候我们想控制一下堆中的对象实例的状态,比如操作一下它的方法,使用一下它的属性怎么办?于是,Java推出了一种叫做引用类型的东西。在利用new关键字创建对象的时候,同时也创建一个叫做"引用"的东西存储在堆栈中,那么程序运行的时候,可以通过引用来操作堆中的对象,如果使用完毕。则堆栈回收引用所占的空间,那么对象可能将不再得到使用,则被垃圾回收器回收,如果可能在程序后期还会涉及到这个对象的使用,那么可以将它的引用进行传递或者是保存起来,待下次想用的时候及时取出即可,也就是说,你想操作堆中的对象,必须通过"引用”。(后面会涉及到的引用传递问题,核心就是这里的解释)。个人认为,因为现实世界中的类型非常多,所以需要给在堆栈中的东西取一个统一的名称,Java中将它命名为"引用类型",表示了它对堆中一个对象的引用的类型、同时,这个对对象的引用就是这个引用类型的值,那么,能不能直接创建一个空引用而没有对象呢?可以,那么这个时候,这个引用类型的值就是null,表示了它暂时还没有引用一个对象实例,你需要创建,往后我们在编程中遇到一种常见的错误–空指针错误,就表示你的引用类型值为null,在堆中还未创建对象。
  • 2、 整数的运算符以及运算规则(“你能用的运算符全在这里了!”)

    • ⑴、Java语言提供了很多作用于整数值的运算符:
      特别提示: 在介绍整数值的运算符之前,还需要提一个问题,就是如果参与运算的两个数的类型不相同如何处理?比如一个数是long类型(64位),一个数是int类型(32位),怎么计算?这里涉及到一个很重要的规则。如果两个操作数类型一致,则直接进行计算,如果两个操作数类型不一致,那么需要判断这两个操作数的类型之间能不能相互转换,转换的规则如下:
      整数类型(byte、char、short、int、long)之间能相互进行转换,低位数的类型会自动向高位数类型转换,比如一个int类型与一个long类型进行计算,那么int类型会自动转换成long类型。一个short类型与一个int类型进行计算,那么short类型会自动转换成int类型,也就是说低位数类型在与高位数类型进行运算的时候,会自动转换成高位数类型,并且得到的结果也是高位数类型!(如果是需要将高位数类型向低位数类型转换,则需要进行强制转换,这个内容在讨论强制转换操作符的时候再详细描述)。
      那么整数类型和浮点数类型(float、long)之间如何进行计算呢?当整数类型和浮点数类型之间进行计算的时候,会将整数类型转换成浮点数类型,再按浮点数类型的运算规则进行运算(浮点数运算规则有专门的章节进行了讲解),同时,得到的结果也是浮点数类型。我们来试验一下:
      long类型与float类型之间进行运算(整数类型的最高位类型与浮点数类型的最低位类型):
      整数类型与浮点数类型进行运算,结果是浮点数类型!
      布尔类型不能与整数进行运算,因为它们之间不能进行相互转换!
      整数类型不能与布尔类型直接进行计算!
      下面我们来详细了解一下与整数类型有关的运算符。
      这里讨论的范围都仅限整数类型(byte、char、short、int、long),混合类型的运算会有专门的章节进行讨论,请及时关注博文更新!
      还有一个问题需要强调: 如果没有特别说明,以下内容涉及到整数的都是int类型的整数!
      • ①、比较运算符一共有6个(">","<",">=","<=","!=","=="),结果类型为布尔类型(这些运算符都很常见,就不一一介绍了):

         // 比较运算符左右两边的操作数都是整数类型,
         //结果类型为boolean,
         //表示运算结果是真还是假(true or false)
             public boolean a = 3>5//表示大于关系
             public boolean b = 5>=3//表示大于等于关系
             public boolean c = 3<=5//表示小于等于关系
             public boolean d = 3<5//表示小于关系
             public boolean e = 3==5//表示相等关系,
             //单个"="是赋值
             public boolean f = 3!=5//表示不等关系
             //比较运算符左右两边除了可以是确切的值
             //以外,还可以是整数类型的变量
             //先声明两个整数类型的变量:
             public int a = 5public int b = 6public boolean i = a==b;
        
      • ②、数值运算符
        数值运算符一共有16个(’’+","-"," * “,”/","%","++","–","<<",">>","<<","~","&","^","|","? :","()"),结果类型为参与运算的更高位数类型、解释请参照开头的特别提示,有一些可能不常用,此处将进行一一介绍。
        1、一元加减运算符:"+"、"-"。
        它们的功能就是简单将左右两边的数取和或者取差。
        2、一元乘法运算符:"/"," * “,”%"。
        “/”," * “–它们的功能就是简单将左右两边的数取积或者取商。
        但是”%"是取余数操作,能直接获得两数相除的余数:

        // 如果想得到105除以11的余数是多少,可以像如下操作
          public int a = 105%11//a的值就是6
        

        取余操作实例!
        3、自增自减运算符:"++"、"–"。
        需要重点强调的是,它们的操作数只有一个,不像一元加减乘除运算符一样的操作数有两个,功能就是简单地将一个数的值加1,但是容易产生混淆的地方在于,它们放置的位置。即可以放置在一个数的前面,也可以放置在一个数的后面。

        // 自增自减运算符前置
            public int a = 5
            public int b = ++a;
            public int c = a--//自增自减运算符后置
            public int a = 5public int b = a++public int c = a--

        那么放在前面和后面到底有什么区别呢?
        实际上这个运算符是根据操作变量的实际需求而特别创建出来的。
        那么,变量是什么呢?你编写的每一行Java代码,在运行的时候都会对应至硬件的操作,声明一个变量(public int a = 5;)实际上代表的就是在Java堆栈里新开一个内存空间(这个空间的类型是int,换句话说就是这个空间只能存储int类型的值,也就是32位,空间的名称是"a",空间的值是5),然后把你赋给变量的值存储在空间里。通常在代码中都是声明一个变量的时候就赋值,这个操作叫做变量的初始化。然后在接下来的编码过程中可能会不断修改这个变量的值(也就是修改这个变量的内存空间所保存的值),以达到某种编程目的(功能)。
        了解了以上的内容之后,再回过来看这个自增自减运算符。它的作用其实就是能直接将变量的值直接+1或者直接-1。而前置和后置的区别就在于这个+1或者-1的时机。
        如果想使用一个变量的值,在使用完之后让这个值立即+1。那么很明显是后置(因为是先使用值再+1)。
        如果想先+1,再使用值,那么很明显是前置(因为是+1,再使用)。在一般的开发中,多半使用后置。除非是特别的功能需求,或者是编程目的,才会使用前置,如果了解了实质,那么,使用起来就会得心应手。
        还有一个问题,很多人会疑惑。比如a和a++是什么关系?a++会不会比a大1。不会,其实这个也很好理解。a和a++都是变量标识符,都指向同一块内存区域的同一个值,甚至你可以说a和a++其实是完全相同的,如果你不想让a表示的内存空间的值自增,就直接在代码中写a,如果你想让这个内存空间在这次使用完之后自增,就直接在代码中写a++。a++只是比a多一个自增的功能,其他完全一样。
        如果还理解不了,我们再从另一个角度来理解,比如,你在代码中声明了一个整数变量:int a = 5;这个时候你又写了一行代码:a++;那么这个时候你知道标识符a代表的那个内存空间的值会自增1,那么自增了1之后的值是6,那么这个6的标识符还是a,并没有换。所以,你继续写一行代码System.out.println(a),将a的值打印到输出台,我们都知道是6。如果这个时候我们继续写一行代码System.out.println(a++);那么打印出来的值是几呢?是6。因为是后置的,先使用值(a的值就是6),再自增。所以总结起来就是,自增自减运算符会改变变量的值,但是不会改变变量的标识符,a和a++表示的值是相等的,只是a不会自增,a++会。
        PS:++a的情况请自己根据上面的推理得出结果。
        自增自减运算符在for和while循环中很常见。
        4、移位运算符:"<<"、">>"、">>>"
        移位运算符的基础是二进制码,如果你用移位运算符操作一个整数,那么整个运算过程就是:先将十进制整数变为二进制表示,然后对二进制表示进行移位操作,再将结果的二进制表示转换成十进制的整数,即为结果。
        比如在控制台直接打印5向左移(<<)3位的结果:
        5向左移3位的结果示例!
        左移需要强调的问题是,所有的二进制位都是向左边移动,一直都是在右边补0,所以符号位(第32位)不会被影响,负数永远是负数,正数永远是正数。那么,又会有一个疑问。int类型是32位的,如果左移32位,那不是要补32个0吗?如果正数不就变成0了?负数也是0?那我们来看一下实际的情况:
        正整数左移32位值还是它本身!
        负整数左移32位值还是它本身
        实际情况是,正数左移32位还是它本身的值,负数也是,由此我们可以推断出,"<<“不会影响值的符号,正数永远是整数,负数永远是负数。并且左移32位或者是32的整数倍都是它本身,所以,左移的总结就是:左移不会影响数值的正负,并且左移32x+y位(x,y=1,2,3…正自然数)的值都是相等的。
        比如40向右移(>>)3位的结果:
        40向右移3位的结果示例!左移和右移互位反操作
        我们都知道,负数的符号位是1,右移也是补0,那么如果是负数右移的话,会不会影响符号位?我们来试验一下:
        负数右移不会影响符号位!
        结果是,负数右移,不会影响符号位,除符号位外空缺补0,符号位不变,那么移32位是什么情况?
        负数移32位还是它本身
        通过试验可以得出结论,负数移32位以及32的整数倍还是它本身。
        由此我们可以推断出,”>>“不会影响值的符号,正数永远是正数,负数永远是负数。并且左移32位或者是32的整数倍都是它本身,所以,右移的总结就是:右移不会影响数值的正负,并且左移32x+y位(x,y=1,2,3…正自然数)的值都是相等的。
        还有一种是无符号的右移(”>>>")那么,什么叫无符号的右移呢?这个需要结合"<<"、">>“来说,上面已经知道了”<<"、">>“这两个操作符是不会影响操作数的正负的,那么很显然”>>>“会影响到数的正负,下面我们来看几个试验代码(为了更详细,此处将提供二进制码表示):
        -65>>>1(-65进行无符号右移1位):
        -65无符号右移1位结果是2147483615!
        结果有点出乎意料,我们从二进制码来看一下具体情况:
        -65的二进制表示是:
        1111 1111 1111 1111 1111 1111 1011 1111
        那么无符号位右移1位的结果是:
        0111 1111 1111 1111 1111 1111 0101 1111
        我们发现,结果的符号位是0,是一个正数了。也就是说”>>>“连同符号位一起移动了,空缺补0,那么0111 1111 1111 1111 1111 1111 0101 1111转换为10进制表示就是2147483615。
        接下来右移2位、3位…31位都是在0111 1111 1111 1111 1111 1111 0101 1111的基础上移动,结果很清晰了。
        如果移动32位呢?按照上面的思路,移动32为就全部都是0了,那转换成10进制就是0。我们来试验一下:
        -65无符号右移32位还是它本身!
        从结果中可以看出,负数无符号右移32位不是0,而是它本身。
        所以,总结无符号右移(”<<<"):如果是负数进行无符号右移,因为移位后空缺处补0,所以最终会变成正数,而正数符号为本身就是0,所以移位后还是正数。任何一个数无符号右移32位或者32的整数倍,结果还是它本身、同时无符号右移32x+y(x,y=1,2,3…正自然数)的值都是相等的。
        那么,为什么没有无符号左移(">>>")呢,因为左移不涉及符号位的移动,所以就算有无符号左移">>>",它的作用和">>“实际上是完全一样的,所以仅设置”>>“既可,无需设置无符号左移(”>>>")。
        PS:移位的值还能是负数,比如5<<-28的值是80。
        实际操作示例:
        5左移-28位示例!
        个人认为在正常编程范围内,顺着来已经足够用了,如果有兴趣,可以对这种移位是负数的情况进行深入了解。此处不再描述。
        5、按位补码运算符("~",它只有一个操作数)
        “按位补码运算符"这个叫法是官方文档里的叫法,其实这个操作符按照用法更形象的叫法应该是"按位取反运算符”,另外一个叫法是"按位非运算符"。
        它的运算规则是,将操作数转换为二进制表示,然后将二进制表示的1变为0,将0变为1,得到的二进制再转换成10进制表示,即为结果。
        比如:
        5的二进制表示是:
        0000 0000 0000 0000 0000 0000 0000 0101,那么按位补码操作的过程就是将0变为1,将1变为0,这里也包括了符号位!得到的结果是:
        1111 1111 1111 1111 1111 1111 1111 1010。
        我已经知道了负数的二进制表示是正数的二进制位全部取反再+1。所以我们进行逆运算,得知5按位补码操作后的结果是-6。
        实际结果试验:
        5按位补码后的结果是-6!
        6、整数位运算符("&"、"^"、"|",它们都有两个操作数)
        “整数位运算符"是官方文档的叫法,实际上,更形象的叫法应该是"按位逻辑运算符”,分别是"按位与"("&")、“按位或”("|")、“按位异或”("^")。它们会将两个操作数都转换为二进制表示,然后分三种逻辑(“与”、“或”、“异或”)分别计算二进制的每一位,最后再将得到的二进制结果转换为十进制。下面分别介绍这三种逻辑是如何计算的。
        short类型与int类型计算自动转换示例:
        short类型与int类型计算时自动转换为int,且结果类型为int!
        char类型与int类型计算自动转换示例:
        char类型与int类型自动转换示例!
        boolean类型与int类型进行计算,甚至不能通过编译,说明二者之间不能直接转换:
        boolean与int类型不能直接进行计算!
        按位与("&"):
        计算规则是,首先将两个操作数转换成二进制表示,同时统一类型以及存储空间(参考之前的特别提示:),然后将两个操作数的每一位二进制分别计算,两位都是0,结果为0,两位都是1,结果为1,如果一个是1,一个是0,结果为0。
        比如:5&9(为了方便,这里使用byte类型,8位)
        5的二进制表示:0000 0101
        9的二进制表示:0000 1001
        结果为: 0000 0001,也就是1。
        5&9计算结果示例!
        按位或("|"):
        计算规则是:两位都是0,结果为0,两位都是1,结果为1,如果一个是1,一个是0,结果为1。
        比如:5|9(为了方便,这里使用byte类型,8位)
        5的二进制表示:0000 0101
        9的二进制表示:0000 1001
        结果为: 0000 1101,也就是13。
        5|9计算结果示例!
        按位异或("^"):
        计算规则是:两位都是0,结果为0,两位都是1,结果为0,如果一个是1,一个是0,结果为1。
        比如:5|9(为了方便,这里使用byte类型,8位)
        5的二进制表示:0000 0101
        9的二进制表示:0000 1001
        结果为: 0000 1100,也就是12。
        5^9计算结果示例!
        虽然布尔类型和整数以及浮点数之间不能相互转换,但是布尔类型相互之间也能进行按位与、或、异或(注意:布尔类型没有按位非操作):

        下面直接上示例:
        "&"操作只要有一个是false结果就是false!
        "|"操作只要有一个是true,结果就是true!
        "^"操作只要两个都相同就是false!
        根据示例能总结出:
        按位与("&")
        两个布尔类型值都为true,结果为true,只要有一个是false,结果就为false。
        按位或("|")
        两个布尔类型值只要有一个是true,结果就是true,只有两个都是false的情况下,结果才是false。
        按位异或("^")
        两个布尔类型值只要相同,结果就是false,只要不同,结果就是true。
        在实际的编程中,我们一般比较少利用按位与、或、异或对布尔类型进行操作(因为它们一定会计算两个布尔类型的值,尽管可能在得到第一个类型的值的时候就能获知表达式的结果),更常用的是一种短路运算,名称分别为逻辑与("&&")、逻辑或("||")(实际上,如果严谨的来说,"&"、"|"、"^“用于布尔类型运算的时候,可以称之为非短路"逻辑与”、“逻辑或”、“逻辑异或”,因为布尔类型的运算是一种逻辑表示)。从布尔类型运算的特点来看,我们很有可能在知道第一个布尔类型值的时候就能预知结果,第二个布尔类型值完全可以不需要知道,因为无论它是任何值,都不影响结果,所以"&&“和”||“就有这种效果,如果在已知第一个布尔类型的值的情况下就能得到结果,第二个布尔类型值将直接被忽略,不再进行计算。
        逻辑与(”&&")的运算规则:
        只要有一个值是false,结果一定是false,所以利用"&&“对布尔类型进行运算的时候,第一个布尔类型的值是false,那么第二个将直接被忽略。
        如果两个布尔类型的值都是true,结果才是true。也就是说,第一个值为true的情况下,才有必要对第二个值进行计算。
        逻辑或(”||")的运算规则:
        只要有一个值是true,结果一定是true,所以利用"||“对布尔类型进行运算的时候,第一个布尔类型的值是true,那么第二个将直接被忽略。
        如果两个布尔类型的值都是false,结果才是false。也就是说,第一个值为false的情况下,才有必要对第二个值进行计算。
        逻辑与(”&&")、逻辑或("||")是布尔类型特有的运算符!

      • ③、条件运算符(" ? : “)
        条件运算符有两个符号,第一个是”?",第二个是":"。我们先来看一个具体的例子,直接上代码更快理解:
        int a = c>b?c:b;
        这个表达式的意思是:首先,声明了一个int类型的变量,标识符为"a",然后需要给这个a 赋值。一般我们都是直接int a = 5;就是直接使用字面量值(5这种就是所谓的"字面量值"),但是这里使用了另外的表达方式, 直接用一个变量赋值给变量,这也是允许的,那么后续的"c>b?c:b"是什么意思呢?之所以称之为条件运算符,是因为存在条件的,这个条件是什么?条件就是"c>b"这个表达式是否成立?如果成立那么整个表达式"c>b?c:b"的结果就是":“左边的值,也就是c,如果不成立,就是b。所以完整的描述的就是:我在给int类型的变量a赋值,但是有两个选择,一个是c,一个是b,所以在赋值的时候,先比较一下大小,如果c大于b,则将变量c的值赋给变量a,否则将变量b的值赋给变量a。
        我们可以看出,条件运算符以”?“为中心,左边的是一个结果为boolean的条件表达式,右边是结果的选择,结果的选择仅限两种,用”:“分隔,如果boolean结果为true,则结果为”:",否则为":"右边。
        实际操作示例:
        条件操作符示例!
        条件运算符在实际中最常用的例子就是翻页功能的实现。
        比如,你规定一页只能显示10条数据,那么,可能存在两种情况,一种情况是总的数据量刚好能整除10,那么你的总页数,就是总数据量除以10,还有一种情况就是总的数据量不能整除10,还有余数,比如63,那么你的总页数就需要在总数据量除以10得出的结果再+1。
        所以你经常能看见类似的表达:

        // 声明一个变量保存总的页数
            int PageNumber = 0//声明一个变量保存总的数据量
            int TotalPage;
        //得出计算总页数的计算式
            int PageNumber = TotalPage%10==0?
             TotalPage/10:TotalPage/10+1;
           //用总数据量对10进行取余运算("%"也叫模运算),如果余数为0,
           //说明可以整除,所以总页数就是总数据量除以10的结果,
           //如果余数不为0,说明不能整除,那么就需要在除法运算
           //的结果上+1;
        
      • ④、强制转换运算符
        强制转换运算符一般用于将内存容量大的数据类型转换为内存容量小的数据类型,比如将64位二进制的long类型转换为32位二进制的int类型,将IEEE 754 32位表示法的double类型转换为IEEE 754 64位表示法的float类型,这种转换直接涉及到内存空间的转换。
        比如要将64位的long类型直接转换为32位的int类型就是很直接的将64位中的前32个零直接抹掉, 剩下的32位二进制是多少那么转换的结果就是多少。所以说,强制转换容易丢失精度,如果一个数值已经超出了int类型的数值范围(-231–231-1),在强制转换为int的过程中,也就是将前32位直接抹掉的过程中,会损失一部分有效的二进制表示位,转换得到的结果较转换前的值会有变化,所以强制转换操作一定要谨慎!下面展示如何用代码表示强制转换:

        // 将long类型强制转换为int类型
        //首先声明一个long类型的变量,标识符为a,
            public long a = 635398563562956561l,
         //声明一个int类型变量来接受long类型,
         //这个时候如果要将a强制转换为int类型
         //则需要在标识符a前面加上强制转换符
         //(int),这样就将a强制转换为了int类型。
         //变量a将由64位存储立即变为了32位存储
            public int b = (int)a;
        

        我们来看一下实际操作的结果:
        超出int类型范围的值在强制转换后丢失了精度,导致结果是负数!
        从结果可以看出,635398563562956561用32位二进制已经无法表达,超出了int类型的数值范围,在强制转换类型的过程中损失了精度,导致结果是负数。
        强制转换符不仅在基本类型中能使用,在后面即将提到的对象类型转换中也能使用,可以在父子类型之间相互转换。

      • ⑤、字符串连接运算符
        因为字符串属于引用类型,不属于基本数据类型,所以这里将不详细描述,在这里,只需要知道还有这么一个东西就型。在解读字符串的博文中会详细提及!

      • ⑥、对象类型判断符(“instanceof”)
        这个操作符属于引用类型,将在引用类型的章节进行详细描述,在这里只需要知道有这么一个东西就行。

    • 3、Java中有关运算的特殊情况说明(“这些情况你必须知道”):
      • ⑴、除数为0 相信你在初中的时候就知道了,数学里有一个很特殊的值:0,为了这个0,曾经在数学界掀起了一股讨论的热潮,这里我们暂且不去管这个讨论进行的有多么激烈,我们只需要知道这个讨论还是有意义的,因为,得出了两个很伟大的结论:1、0除以任何数结果都是0;2、任何数都不能除以0。如果你不同意这两个结论,或者你有更伟大的发现,请及时告知我,下面我们来详细解读一下这8种基本类型是如何处理这两个结论的
        • ①、基本类型:
          首先我们先看一下示例,就直接上代码了:
          byte类型除以0:byte类型除以0导致程序报错!
          这里提一个题外话,我曾经听说,英语不好就学不好编程或者说在没学好英语之前先不要学编程,从我个人的经历来说,有99.9%不是真的,我相信得出这些结论的人其实并没有尝试去全面了解(这里还不涉及全面学习,只是一个全面的了解)编程,你要学好编程跟英语好不好其实关系不大,其他编程我不敢下结论,Java编程是不涉及什么动词,名称,副词,主语,谓语,宾语,定语,状语,补语等等,说白了,你把那38个关键字认清楚了就行,然后把它们之间的逻辑关系、位置摆放关系、意义等再搞搞清楚,基本上就算入门了。如果你相信天道酬勤,勤加练习,学好是一点问题没有,难就难在,编程实际上是一门艺术,如果想在艺术层面上有所造诣,那是相当困难的。需要持之以恒以及不断的思考,最重要的,个人认为是你需要经常花点时间总结,并且,你写过的代码(可以是你瞎搞,乱写,天马行空等等产生的代码)最好能全部保留下来,在之后的时间里,用你的所见所闻所感所思所想去改进它!在这里,祝所有的码友2019心想事成!
          好了,我们接着说,先来看一下控制台报错的内容:
          Exception in thread “main” java.lang.ArithmeticException: / by zero
          at com.Constructor.ww.Test.main(Test.java:6)

          "Exception"表示的是异常(好像在我的经历中,运行时都称异常,编译时都称错误、我不知道错误和异常有什么本质的区别,反正在我看来,它们都让程序卡住了。仅此而已),在这里是运行时异常,不是编译时错误,因为除0的表达式是可以通过编译的,"in thread "main"表示的是出现异常的线程名称(单词thread就是线程的意思,有关线程的知识,后期博文会有专门的板块详解)、这里能显示线程名称真的是Java一个很人性化的设计,因为你在多线程环境下,可以通过给每一个线程命名从而快速找到出现异常的地方,非常节省时间,java.lang.ArithmeticException是异常的名称(Java中有一个专门的类:Exception,对,就是这个报错信息开头的这个单词,它代表了一系列类似的异常,它有很多的子类,每个子类都代表了一个异常、在这里出现的是它其中的一个子类:ArithmeticException),by zero__代表的是异常的根本原因(大神一般看到__ArithmeticException__心里就有数了,菜鸟一般还需要继续看到__by zero),表明你的代码中有除以0的情况,__at com.Constructor.ww.Test.main(Test.java:6)__显示了具体出错的位置,这个里面的"main"不再是线程名称了,而是代表"main"方法,"6"表示你出错的位置是你代码中的第6行:
          控制台显示的数字实际上是与代码行数有关!
          在以上的代码中,按正常的执行逻辑,应该是在控制台打印出a/0的结果,但是实际上,程序无法执行完毕,因为执行到第6行的时候,就被"java.lang.ArithmeticException"这种类型的错误卡住了,程序报错。我们继续看一下剩下的整数类型是什么结果。
          char类型除以0(char有两种情况):
          1、声明为字符char字符除0报错!
          2、声明为数字
          char数字除0报错!
          short类型除以0:
          short类型除以0报错!
          实际上,int类型和long类型结果与byte也一样。
          那么0除以0是什么结果?我们来看一下:
          0除以0和其他数值除以0没什么区别!
          0除以0也是报"java.lang.ArithmeticException"错误,和其他整数数值是一样的结果。
          我们再来看一下0除以整数是什么情况:
          以int类型为例:0除以int类型结果为0
          从结果来看,没有出什么意外,实际上0除以byte,char,short,int,long结果都是0。所以在J整数运算中需要特别注意避免除数为0的情况!
          PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正!

猜你喜欢

转载自blog.csdn.net/ruidianbaihuo/article/details/87285753
今日推荐