zoukankan      html  css  js  c++  java
  • 死磕Java基础---数据类型和运算符

    一个自学的程序员,带你补牢Java基础!—–ithuangqing

    变量

    在学习之前我们有必要先来看一下什么是变量,变量在Java中就是可以改变的量,说的准确点即使在程序执行过程中,其值在某个范围之内是可以改变的

    变量的定义格式如下:
    数据类型 变量名(标识符) = 字面值;

    我们的变量名是以字母,$和_开头,其他随意,当然除了特殊符号(@和#等)和空格

    Ok,接下来让我们正式开启数据类型和运算符之旅,有请庆哥和小白出场!

    华丽的分割线

    在Java中,任何的数据都是转换成二进制保存在Java内存中,记住这句话!

    庆哥:你知道Java中的八大数据类型吗?

    小白:这个当然知道,

    数据类型

    在Java当中,数据类型分为基础数据类型和引用数据类型,我们需要熟记八大基本数据类型

    基础数据类型

    整型
    Byte short int long

    浮点型
    Float double

    字符型
    Char

    布尔型
    Boolean

    庆哥:可以啊,你记得不错啊,那么你知道什么是内置类型吗?

    小白:内置类型?这个还真不知道,什么是内置类型啊

    庆哥:哈哈,其实内置类型就是基础数据类型啦,八种基本数据类型,也叫做内置类型,是我们在编程中使用最为频繁的数据类型,除此之外就是引用数据类型,在Java中,除了八种基本数据类型之外,其他的都叫做引用数据类型,那么你对各个数据类型,了解的如何呢?

    小白:这个还真的是不太了解,我目前也就是只能说出个八大数据类型,然后对一些常用的也就是常识啦,有所了解,具体的还真的没有深入了解过呢?

    庆哥:对于数据类型可以说是Java中的基础知识了,但是对于基础知识我们一定要掌握牢固,千万不能只停留在表面,很多东西我们不仅要知其然更要知其所以然,所以,基础的东西,我们必定要认真对待啊,今天,咱们就一起深挖这个数据类型吧!

    小白:确实,基础的东西最容易被忽略了,是最容易让自己出错的地方,所以很有必要好好学习一下基础,做到熟练掌握,那么,我们是不是要对八大数据类型做单独的学习啊?

    庆哥:对的,我们需要把八大数据类型都拿过来探讨一下,这样才会让我们记忆的深刻,做到熟练掌握。

    小白:真好,那么,我们应该是从整型就开始吧

    庆哥:对的,接下来,我们就好好说说这个整型

    整型

    小白:整型数据类型就是指的byte short int long这四个家伙吧

    庆哥:对的,就是他们,我们要记住整型数据类型就是指的byte short int long,对于整型数据类型,我们一定要记住的就是他们只能用来接收整型,什么意思呢?简单的说就是他们能接收小数吗?当然不行,整型数据类型只能够用来接收整型。

    小白:也就是说绝对不可以使用整型来接收小数,但是,如果使用整型来接收小数,会出现什么问题呢?

    庆哥:那么我们就来实际操作一下吧

    这里写图片描述

    我们这里举一个很简单的例子,我们使用int去接收一个小数,然后程序直接报错,我们查看报错原因,意思就是我们需要给a赋值一个int类型的,但是却找到一个double型的数据,也就是类型不匹配,由此可见,我们根本没法使用整型去接收小数

    小白:我记得,这里好像可以使用一个叫做强制转换的方式来使他接收吧?

    庆哥:的确,在数据类型中是可以进行数据类型的转换的,那么我们这里可以怎么做呢?我们可以这样操作。

    这里写图片描述

    也就是把小数强制转换成int类型,这样就不报错了,但是这个a的值此时变成什么看呢?

    这里写图片描述

    可以看到,此时的值变成了3,而不是3.3,所以这样的操作是会造成数据精度的丢失,一般开发中并不建议这样做的

    小白:确实,这样就把值给改变了,对了,这里是不是利用了四舍五入呢?

    庆哥:这个问题提的好,我们一起来看下

    这里写图片描述

    如果真的是按照四舍五入的话,那么这里的a应该等于4才对,但是实际的值却是

    这里写图片描述

    小白:我天,这个强制转换真坑,要是放在钱上那不就亏大了

    整型接收范围

    庆哥:哈哈,那倒是,关于这个强制转换,我们需要单独说一下,但是在此之前,我们需要先把这个整型给搞定了,我再问你个问题,你知道这些整型数据类型的为什么会分byte short int和long吗?

    小白:这个好像是因为他们各自能接收的数字大小是有范围的吧

    庆哥:对,那么你知道他们各自接收的数字大小范围吗?

    小白:我好像只记得byte,它的范围好像应该在-128到127之间,其他的我倒是还真记不得了

    庆哥:可以,你还记得byte的范围,我们看
    这里写图片描述

    当数字大小超过127的时候就会报类型不匹配的错误了,那么他们四个的接收范围到底是多少呢?

    byte 的取值范围为:-128到127

    short 的取值范围为:-32768到32767

    int 的取值范围为:-2147483648到2147483647

    long 的取值范围为:-9223372036854775808到-9223372036854775807

    小白:庆哥,这个不用记吧,我感觉我都记不住,另外我们有什么办法可以获得这些值吗?

    庆哥:这个确实不用记,但是我觉得吧,像byte,short和long如果你真要记的话也不是很难的,那么我们如何得到这些值呢?我们可以这样做。

    这里写图片描述

    我们通过以上代码就可以获得这四个整型的接收值的范围大小了

    小白:不过这里面我有一个疑问,这个integer是什么啊

    庆哥:这里是使用到了四个整型数据类型相对应的包装类来获取具体的取值范围,integer即使int对应的包装类,那至于什么是包装类,我们后面也会单独来讲,不要着急、、

    小白:哦哦,可以的,那么看到他们的取值范围大小,我们是不是就可以选择合适的数据类型来接收数据了

    庆哥:理论上是的,那么,假如现在我有一个值5,那么你觉得用什么来接收比较好呢?

    小白:byte的取值范围是在-128到127,那么使用byte就可以接收吧

    庆哥:确实可以接收,我们看这个代码

    这里写图片描述

    我们发现,使用这个三个都可以接收,但是如果是你,你会选择哪个呢?

    小白:那就选择使用byte呗,这些都是要开辟空间,本着合理利用空间的原则,使用byte比较好吧,,,,不对,我记得平常对于数字我好像用的都是int,这是怎么回事,有点晕了。

    为什么都用int接收

    庆哥:别晕,别晕,你已经发现问题了,根据他们的整型取值范围来说,好像使用byte就可以了,但是在实际的开发当中我们好像使用的都是int吧,这是为什么呢?

    其实不难理解,我们知道byte的接收范围是-128到127之间,但是,我们来看这个

    byte a = 10;
    byte b = 50;

    你有没有想过如果a和b进行运算的话你该用什么来接收它的结果

    小白:这个要看他们做什么运算吧,如果是加减的话依然可以使用byte啊,但是两者如果相乘好像就超出了byte的接收范围啊

    庆哥:是的,如果两者相乘的话就不能再使用byte来接收了,那我们是不是可以使用short来接收,不过你再看这个

    short a = 200;
    short b = 300;

    这个时候跟byte的情况差不多,如果两者相乘的话,就会超出short的接收范围,你有没有发下什么问题呢?

    小白:就觉得这样好麻烦啊,还要考虑是不是超出范围接收,如果不知道他们的接收范围也就是对这点不熟悉的话,那么遇到这中问题就会懵了吧

    庆哥:的确,因此,你会发现我们在日常的开发中凡是涉及整型数据类型的运算我们都是使用int,因为从int的接收范围来看,我们在开发中遇到的大部分数据基本上都可以使用int来接收的,因此,为了方便同意,在Java中,凡是整型数据类型的运算我们统一使用int,
    就比如,我们通常这样

    int a = 10;

    而不是

    byte a = 10;

    或者

    short a = 10;
    小白:哦哦,原来是这样啊,这下就明白了。对了,庆哥,我记得关于int我还经常听说另一句话那就是int占四个字节,这里说的四个字节具体咋回事啊,有点不太懂?

    庆哥:首先你要知道byte就是字节的意思,是在Java中存储的基本单元,一个字节就是8bit,那么bit又是什么呢?bit就是位的意思,也就是一个字节就是8位,那么位又是什么呢?在Java的存储中都是将数据转换成二进制进行存储,也就是0和1的形式,那么一个二进制数据的0或者1就是1bit

    我给你举一个例子吧,byte的接收范围是-128到127之间,byte占一个字节,也就是八位,那么我们拿最大的127来说,它的二进制是1111111,再比如67也在byte的接收范围之内,它的二进制是1000011,我们可以看到无论是127还是67他们呢二进制中的0和1加起来一共7位,而byte是占一个字节8位所以可以盛装这些数据,明白了吧

    小白:哦哦,明白了,原来是这么回事啊,你刚才说在Java中数据都是转换成二进制进行存储的?

    庆哥:是的,比如我们定义一个int a = 10 那么是如何将这个10存储到内存中呢?答案就是把它转换成二进制进行存储

    小白:其实在学习Java的过程中,我一直对进制转换比较陌生,因为觉得好麻烦啊,也没有认真记过,所以这块听薄弱的

    庆哥:进制转换可以说是基础中的基础,总的来说就是二进制 八进制 十进制 十六进制之间额转换,但是会牵涉一些其他的问题,所以这块咱们找时间作为一个单独的专题来说一下。

    小白:可以可以,对了,byte占一个字节,那么其他的呢:

    庆哥:byte是占一个字节,short占两个字节,int占四个字节,long则是占八个字节,float占四个字节,double占八个字节,char占两个字节,而boolean则占一个字节。

    小白:ok,这下总算记清楚了,那么关于整型数据类型我们到这里是不是说的差不多了

    庆哥:关于整型我们还要说一下long类型

    Long类型

    庆哥:为什么要说一下这个long呢?因为它稍微有点不一样,比如我们在写long类型数据的时候一般是这样的

    long a = 100L;

    什么意思呢?也就是说我们定义long类型的数据的时候一般都要在数字末尾加上一个L,当然大小写都可以,但是因为小写的L特别像阿拉伯数字1,因此建议都采用大写,容易区分。

    小白:原来是这样啊,我说之前怎么见一些数字的末尾有一个L啊,当时还纳闷呢?仙子啊知道怎么回事了

    庆哥:那么接下来我们就来说一下浮点型数据吧

    浮点型

    小白:我总感觉这个浮点型是比较陌生的,反正就感觉int比较熟悉,其他都有点陌生

    庆哥:确实啊,那是因为我们平常使用的int是最多的,用的多也就熟悉了,对于浮点型我们主要就是来探讨float个double的,而且我们要注意float被称为单精度数据类型,而double则是双精度了,在实际的应用中我们使用double会多一点,另外我们要注意,比如一个小数3.33,如果你这样写的话它陌生的数据类型就是double了,只要在其末尾加上F才表示float类型,也就是这样3.33F,这就是一个单精度float类型数据,当然为了方便记忆,对于double类型我们一般也在末尾加上D,就比如3.33D这就是一个双精度double型数据。

    数据类型的作用何在

    对了,我问你一个问题吧,你知不知道我们为什么要使用数据类型呢?也就是说数据类型的作用是什么?

    小白:这个,还真是不清楚

    庆哥:其实数据类型的作用就是决定了要在Java的内存空间中开辟多大的内存空间来存储你的字面值,比如int a = 5,那么你的数据类型是int,占四个字节,也就是32位大小,因此就需要在内存空间格尼开辟四个字节的空间供你存储你的值,也就是这里的5,而这个5最终是要转换成二进制进行存储的,这个之前已经说过了。

    小白:还真是处处皆学问啊

    庆哥:另外再说一个小的知识点,在浮点型中数据的默认数据类型都是double,而且对于一个这样的小数double a = 0.2345D,这个0是可以去掉的,也就是可以写成这样double a =.2345D。这样也是正确的。

    小白:哦哦,又涨姿势了,对于浮点型的话基本上就是以上你说的那些知识点了吧!

    庆哥:对的,对于浮点型我们要记住要在数字的末尾加上相应的F和D,记住默认使用的double就行了,接下来我们来说说这个char吧

    字符型

    小白:字符型是不是和字符串有着很大的关系啊

    庆哥:是的,字符串的本质就是连续的字符数组,比如String a = “你好”,本质上就是char[] a = {‘你’,’好’}.

    对于字符我们要记住,它是使用单引号的,而字符串则是双引号,下面我们来看一个问题,那就是对于这样的一个字符,它是如何存储的呢?

    char a = ‘A’;

    我们知道数据都是转换成二进制后再进行存储,对于十进制我们知道如何转换成二进制,但是对字母又是怎样操作呢?

    这其中就要提到这个了

    这里写图片描述

    小白:我知道我知道,这个ASCII表也是经常听说啊,但是说实话还真的没在意过,哎,怪不得我的基础那么差,原来很多基础的东西我只是停留在表面上啊

    庆哥:是啊,所以说基础是最容易让人忽略了,所以在以后的而学习中千万不要忽略基础,另外你可要记住了,对于char来说,它是只能接收单个字符的,什么意思呢?你能用char来接收10吗,当然不行啊。

    Char和int之间的互相转换

    庆哥:下面我给你出一道题你看下结果

    这里写图片描述

    你说这个的打印结果是多少

    小白:难道不是10吗?

    庆哥:实际结果是

    这里写图片描述

    为什么会是97呢?这里就要说明一个问题那就是其实int和char之间是可以转换的,那么如何转换呢?他们之间的转换就要参考ASCII表了,你仔细看再ASCII表中是不是有对应数字字符的十进制数据,我们可以看到字符1的十进制是49,而字符0的十进制是48,所以结果是97

    小白:怪不得我会回答错,我根本不知道字符1的十进制还有0的,这个怎么记啊,难道每次还要去看ASCII表吗?表示记不住

    庆哥:这个其实有技巧的,我们只需要记住字符0的十进制是48,字符A的十进制是65,字符a的十进制是97就行了,你知道为什么吗?

    小白:让我看看,,,哦,我好像知道了,他们的十进制都是递增的,比如字符0的十进制是48,那么字符1的十进制就是49,都是一次递增的。

    庆哥:对的,你看,不难吧,知识我们平常不注意而已

    小白:确实,在平常的学习中千万不能够眼高手低

    如何判断是字母还是数字还是中文

    庆哥:现在我再来靠靠你,你知道如何判断一个字符串中哪些是数字,哪些是字母以及中文吗?你有什么思路吗?

    小白:我说庆哥啊,这样的问题难度是不是不适合我啊,我都没啥思路,怎么做啊

    庆哥:这个其实就要借助我们之前说的ASCII表了,从字符对应的十进制来说,我们是不是可以得出这样的结论

    [48,57]在这区间的就是数字0-9了
    [65,90]在这个区间就是大写字母A-Z了
    [97,122]在这个区间就是小写字母a-z了

    这个你是否明白呢?

    小白:嗯嗯,这个看着ASCII表就明白了

    庆哥:那好,你看这个字符串我们该如何判断其中的大小字母和数字

    这里写图片描述

    小白:我知道,可以这样做

    这里写图片描述

    庆哥:可以啊,你知道string.charAt什么意思?

    小白:我查了一下就是根据索引得到字符串中的单个字符的

    庆哥:确实,有的时候你会发现你最好的老师就是搜索,遇到问题我们首先要试着自己去解决,不会的不懂的自己先要搜索一下,看看能不能自己解决。

    小白:是的,这样才是正确的自学方式。

    庆哥:以上你是查找出了字符串中的小写字母,那么大写字母和数字也就是相同的道理了,那么你知道如何判断是否为中文呢?

    小白:这个我还真不知道

    庆哥:这个我们可以根据一个汉字占两个字节来判断,有如下这种方法

    这里写图片描述

    记住这个方式即可,接下来我们赶紧去看看布尔型数据类型吧

    布尔型

    小白:对于布尔数据类型,我个人觉得这个还是比较简单的,因为它好像就有两个,那就是真或者假

    庆哥:确实,对于布尔型那就是用来做判断的,我们在日常开发中使用也是获得真或这假这个布尔值,从而去进行一些判断。除此之外基本上就没有什么了,到了这里,突然觉得我们的基本数据类型已经说完了啊。

    小白:就是,怎么突然就已经全部说完了,对了,庆哥,是不是还有一个数据类型的转换没有说啊。

    庆哥:哦哦,是的,下面我们就来说一下这个数据类型之间的转换吧

    数据类型转换

    自然转换
    庆哥:在数据转换中,分为自然转型和强制类型转换,我们先来说一下这个自然转型,在说数据类型转换之前我们必须知道这么一个知识,即这些数据类型之间是存在大小关系的,也就是根据他们的取值范围来说的,有这么一个大小关系

    这里写图片描述

    什么意思呢?我们看这个代码

    这里写图片描述

    我们定义一个byte数据为10 ,然后将其赋值给short,我们知道short是大于byte的,像这种由小的转换成大的就叫做自然转型。

    强制类型转换

    但是我们再来看这个
    这里写图片描述

    我们想把一个int数据使用byte来接收,结果报错,类型不匹配,那么我们该怎么做呢?

    这里写图片描述

    我们可以在c的前面加上一个byte,代表把int型的c强制转成byte型的数据,像这种由大的转换成小的就是强制数据类型转换,其实在开发当中是不建议使用强制类型转换的,因为这样做会造成精度的丢失,比如我们看这个

    这里写图片描述

    经过这样的强制类型转换我们看结果

    这里写图片描述

    强制数据类型转换一般不建议使用,因为会造成精度的丢失

    小白:哦哦,懂了,这就是数类型转换啊,这下明白了!

    引用数据类型

    庆哥:我们对基本数据类型做了大致的探讨,还记得我们之前我们说过吗?在Java中数据类型是分为基本数据类型和引用数据类型的,经过上面的探讨我们已经知道什么是基本数据类型了,那么什么又是引用数据类型呢?

    小白:我觉得吧,除了基本数据类型,其他的应该就都是引用数据类型了吧

    庆哥:这话倒是没错,引用数据类型包括类,接口类型,数组类型等,其实也就像你说的,除了基本数据类型,剩下的就是引用数据类型了

    小白:我特想知道,这个基本数据类型和引用数据类型有什么区别啊?

    庆哥:关于他们的区别,就牵涉到一些内存方面的知识了,对于基本数据类型而言,他们统一存放在栈中,而对于引用数据类型,他们的引用存放在栈中,但是实际的对象却是存放在堆中,至于什么是栈什么是堆,现在你还不用知道记住基本树蕨类型在栈,引用数据类型引用在栈中,对象在堆中即可,也就是他们在内存中存放的位置有所区别。

    包装类

    小白:嗯嗯,这下算是对数据类型有了差不多的了解啦

    庆哥:其实对于数据类型我们还要了解一个东西,那就是基本数据类型对应的包装类,什么意思呢?我们来举个例子

    比如这里,我们想要定义一个方法,我们希望的是这个方法可以接收任意的数据类型,那么这个方法该怎么设计呢?

    这里写图片描述

    那么我们就要思考一下,这个方法的参数我们怎么些才可以传入任意的数据类型。

    小白:这里我们是不是可以使用object作为传入额参数呢?object是所有类的父类

    庆哥:对,你已经说到了问题所在,但是你想,我们如果使用了object,我们可以将我们的byte或者int传入进去吗?别忘了,这些可都是基本数据类型,而我们要传入的可是一个对象,是一个类的对象。
    小白:不对啊,这个我之前做过,也都可以传入啊?

    庆哥:确实,那是因为每一个基本数据类型对应的都有其包装类型,我给你列出来你就会发现了

    byte 对应的包装类 Byte
    short 对应的包装类 Short
    int 对应的包装类 Integer
    long 对应的包装类 Long

    float 对应的包装类 Float
    double 对应的包装类 Double

    char 对应的包装类 Character
    boolean 对应的包装类 Boolean

    怎么样,看到这些包装类,有没有很熟悉

    小白:哦哦,原来是这样,之前我还一直纳闷,有的时候些int值为什么使用Integer,不明白这是个什么玩意,原来是int的包装类啊,不过这些包装类具体该怎么使用啊,要不先给我说说这个Integer吧,感觉比较特殊呢

    庆哥:确实我们看到在八种基本数据类型对应的包装类中,除了int和char其他的都是首字母变大写即可,唯独int和char又比较特殊,接下来我们就以最常使用的Integer来介绍下包装类的使用

    还记得我们之前说的八种基本数据类型的取值范围吗?我们是如何得知这些范围的呢?这就可以使用到我们的包装类

    这里写图片描述

    既然是包装类,也就是一个类,那么肯定就会有相应的方法供我们使用

    这里写图片描述

    我们就是通过这样的方法来获取int的取值范围的,同理,对于其他的数据类型也是一样的。

    我们再来看这个Integer,对于它我们可以这样操作

    这里写图片描述

    我们可以看到对于Integer,它的构造函数允许我们可以传入一个数字或者字符串,然后它会将对应的数字和字符串都转换成Integer类型,如果我们打印a和b的话会打印出对应的数字而非地址,那是因为在打印的时候调用了toString方法,也就是Integer中重写了toString方法。

    小白:那么这里可不可以传入一个这样的字符串呢?

    这里写图片描述

    庆哥:如果你传入的是这样的额一个字符串,编译是可以通过的,但是运行的话就会出错,因为Integer会将传入的数字或者字符串转换成Integer类型,这里就要求你必须是个数字才行,也就是说引号中是数字才行,而不能是其他,像abc是无法转换成Integer的。

    小白:知道了,对了,这里我们只是说了Integer的构造方法,既然把它单独拿出讲,我觉得我们也要掌握它的几个重要的方法吧!

    Integer中的方法掌握

    庆哥:这是必须的啊,对于Integer,我们确实有几个方法是我们需要掌握的额,首先,第一个,就是这个方法,把一个字符串转成int类型的数值

    这里写图片描述

    这个方法可以直接将字符串转成int类型的数值,当然这个引号内也必须是数字才行,另外我们最好也掌握一下这三个方法,分别是把十进制的int转成二进制,八进制和十六进制,得到的是一个string类型的值

    进制转换的方法

    十进制转成二进制

    这里写图片描述

    十进制转成十六进制

    这里写图片描述

    十进制转成八进制

    这里写图片描述

    另外,我们也要记住如下两个方法

    这里写图片描述

    也就是把int和string转成Integer类型的方法,那么到这里,对于Integer的学习也就差不多了

    小白:那么对于其他的包装类型是不是跟Integer的使用方法差不多

    庆哥:对的,类比着进行学习,基本上都是一样的,接下来我们要把重点放在一个很重要的概念上,那就是拆装箱
    小白:这个概念我倒是听过,但是一直没有当回事去学过

    庆哥:这个自动拆装箱属于是在jdk1.5之后的一个特性,我们很有必要去了解一下,而且这个在面试中也很有可能被问到,下面我们就一起来看看吧

    自动拆装箱

    庆哥:对于这个自动拆装箱,我们首先要理解什么是拆装箱,从字面意思上理解大概就是装进一个箱子里,拆开一个箱子,为什么要这样说,这还要从我们的包装类说起,包装类中的包装是不是就很像把一个东西包装起来,包装成一个箱子,这才有了拆装箱啊,我们放在代码中去理解

    我们看这个代码

    这里写图片描述

    上面的代码是不是就是把一个int转成Integer类型,Integer是一个包装类,以上的操作就如同把int型数值进行包装一下变成Integer类型,这个过程就是装箱

    我们再看这个代码

    这里写图片描述

    这行代码就是把Integer类型的a转成我们的int数值,就好比把Integer拆开拿出其中的int,上面这个过程就叫做拆箱。

    小白:原来这就是拆装箱啊,有点比喻的意思,那什么是自动拆装箱啊

    庆哥:以上的写法是再jdk1.5之前,但是再之后我们就不需要那样写了,对于装箱,我们可以直接这样写

    这里写图片描述

    也就是我们可以直接给Integer赋值,它会自动完成装箱,这个就叫做自动装箱

    这里写图片描述

    而对于这个,我们可以直接将Integer类型的a赋值给b,这就是自动拆箱,这样的写法必须在jdk1.5及之后,这就是自动拆装箱啊

    什么意思呢?也就是在jdk1.5之后Integer和int之间是可以自动进行转换的,我们把这个过程叫做自动拆装箱

    小白:原来自动拆装箱那么简单啊,真的很好理解啊

    庆哥:你觉得好理解?那好我们一起来看几道题

    经典问题需牢记

    庆哥:首先,我们看如下代码

    这里写图片描述

    对于上面的代码,你说结果是什么呢?

    小白:我知道凡是通过new的都是创建一个新的对象,那么这里a和b就是两个不同的对象,而==一般就是比较对象地址的吧,因此我觉得这里的结果应该是false

    庆哥:你分析的很不错,这里额记过确实是false,那么你再看这个

    这里写图片描述

    你觉得这个结果是什么呢?

    小白:这个,我就有点不确定了,只管感觉给我就是应该两者是相等的啊,但是如果是相等的话,你也不会问我啊,所以我觉得它还是false

    庆哥:行啊,你,倒是会耍小聪明了,这里的结果确实是false,但是你知道是为什么吗?

    小白:这个还真不清楚,不过觉得应该和咱之前说的自动拆装箱有关系吧

    庆哥:确实,这个就是自动拆装箱的知识,以上的写法我们应该知道就是一个自动装箱的过程,但是你要明白,其实它就相当于这样

    这里写图片描述

    所以结果自然就是false

    小白:那可不可以理解所谓的自动拆装箱就是把这些拆装箱的操作封装起来,使我们可以直接进行赋值操作,但是实际上还是执行了最基本和最原始的拆装箱

    庆哥:对,确实可以这样理解

    小白:这样的话我就明白了

    庆哥:那么我们继续来看个例子

    这里写图片描述

    你说这个结果是什么?

    小白:这个跟之前那个例子不是一样的嘛,结果肯定是false啊

    庆哥:可是实际结果呢

    这里写图片描述

    这是为什么呢?

    小白:纳尼,为什么是true啊,我们上面不才分析了这样的情况吗?那么快就来个反例推翻我们啊

    庆哥:其实这不是反例,而是特例,这里就要说一个知识点了,我们知道对于int,他能够接收的取值范围是-128到127之间,那么如同如下代码

    这里写图片描述

    a 和 b的取值只要在-128到127之间,那么他们指的就是同一个,即使==比较的是两者的引用,两者也是相同的,因为-128到127这些数字是使用频率比较高的,就产生了一个整型常量池,这些数字会存放在这里,有相同的数字则不会再次创建,所以a和b指的是同一个,因此两者相同,当然如果是在这个范围之外的数字,那结果就是false了

    小白:竟然还有这种操作,真的是涨姿势了,这下记住了。

    庆哥:是的,这点需要特别注意了,如果对这块知识不了解,那么面试题碰到的话那就只能靠运气了,好了,关于数据类型我们就说到这,接下来我们需要去探讨另外一个问题,那就是运算符了

    运算符

    小白:说真的,关于运算符,有的时候真的是特别容易迷糊,真的要借这次机会好好梳理一下了

    庆哥:是的,对于这些基础性的知识,关键是你要花时间系统性的学习一下,而不仅仅是靠平常的点滴积累。接下来的时间让咱们一起去好好学习下运算符相关的知识吧!首先我们要知道对于运算符有如下分类

    算术运算符
    赋值运算符
    逻辑运算符
    位运算符
    三目运算符
    比较运算符

    小白:感觉还挺多的啊,难道这些都要一个个仔细研究吗?

    庆哥:这倒是不用,我们把重点放在使用频率比较高的几个运算符就行了,以及注意一些相关性问题即可,首先我们来说一下这个算术运算符,这个是使用的比较多的一种运算符,那你知道什么是算术运算符吗?

    小白:运算符的话不就是Java中的一些特殊字符,用于赋值,比较等,那么对于这个算术运算符我觉得跟数学中的应该是相同的吧,也就是我们经常使用的加减乘除,取余什么的

    庆哥:是的,你说的很清楚,下面一张图列出了所有的算术运算符

    这里写图片描述

    加减乘除是我们的最基本算术运算符,这里我们需要重点关注自增自减和余数,对于其他的一些分配运算符其实是一种扩展的赋值运算符,后面会说
    我们首先来说下加减乘除,这里面我们需要注意一下这个+,要知道它不仅仅是可以做数值运算,同时也可以做字符串的拼接,另外我们要格外注意这个除也就是/,这里面可是有些小陷阱的,下面我们以例子来说

    算术运算符

    减法的注意点

    庆哥:

    我们看如下代码
    这里写图片描述

    你知道最终的打印结果是什么吗?

    小白:第一个a/b应该是0吧,觉得结果应该也是个整型int值,1/3的结果是0.3333…,转成int应该就是0了,至于第二个因为是float那么应该是0.0,而最后一个除数不能为0,这个应该会报错吧

    庆哥:我们看实际的情况如下

    这里写图片描述

    也就是说呢,你只答对了一个,这是为什么呢?

    小白:就是啊,为什么,这个Infinity是个什么玩意,以前从来没有见过啊。

    庆哥:这里就涉及到一些知识点了,首先很重要的一点就是如果是两个整数相除,我们一定要保证使用float来接收,并且被除数和除数有一方是float类型,只有这样我们才能得到我们想要的结果,对于第三个,这个Infinity代表无穷的意思,也就是说被除数如果是float型的话,除数为0会得到正负无穷的结果,而不会报错,当然如果两者都是整数且除数为0那就会报错了

    小白:原来是这么回事啊,你还别说,这个知识点以前还真不知道嘞,这次一定要牢记了

    取余相关的问题

    庆哥:接下来我们就来说说这个取余,也就是%,这个符号叫做百分号,代表取余操作,这里面也有我们需要注意的地方。至于什么是取余操作,我想不用再解释了吧,这里我们记住两个知识点即可

    第一:如果是整除的情况,那么取余操作的结果就是0

    这个是什么意思呢?其实很好理解,我们看例子

    这里写图片描述

    比如说这个,结果一定是0,这个没有什么好解释的,我们看下一个

    第二:如果被除数(分子)小于除数(分母),那么取余操作的结果就是被除数(分子)

    我们也举一个例子你就明白了

    这里写图片描述

    比如这个结果我们可以直接得出100,再比如这个

    这里写图片描述

    不用想,结果肯定是235,那这个呢?

    这里写图片描述

    当然还是一样的啊,就是被除数-362,对于取余操作我们记住这两个基本就差不多了,接下来我们看一个重点问题,那就是自增和自减

    自增自减

    庆哥:对于自增自减问题,如果不好好梳理一番,有的时候真的是特别容易迷,你觉得呢?

    小白:这个真的是深有体会,有的时候会特别纠结,到底应该是先加一还是后加一呢?我想这就是这个自增问题吧!

    庆哥:是的,接下来让我们一起攻克这道难题吧,对于自增和自减,我们要分两种情况来说,这样也方便我们去记忆

    单独使用

    首先就是单独使用,这个是最常见的,就是单独的对一个数值进行自增自减的操作,比如这样

    这里写图片描述

    比如这样对a进行自增,我们看到这个++可以写到前面或者写到后面,但是如果是这样的单独使用的话无论是在前还是在后,结果都是原值加一,在单独使用的时候我们并不能看出自增在前后有什么区别,单独使用的时候大家也不会出错,最容易出错的就应该是在参与运算当中了,所以接下来我们以参与运算中的自增为重点。

    参与运算使用

    小白:这个自减是不是相同的道理

    庆哥:对的,自减和自增其实是一样的,我们在这里以自增为例来进行说明,接下来就好好说说这个参与运算中的区别,我们先来看一个例子

    这里写图片描述

    我们看这个例子,此时的自增已经参与到运算当中,我们来比较a++和++a有什么区别呢?
    此时的结果是什么呢?

    这里写图片描述

    在这里我们一定要记住如下的结论

    **在参与运算当中
    a++ 代表的是先将a的值取出来执行赋值操作,然后再自加一
    ++a 代表的是先将a的值进行自加一,然后再将值取出来进行赋值操作**

    在这里一定要注意“取值”这个概念,很多视频或者书中在讲解这块的时候都会说什么先赋值再加一或者先加一再赋值,但是我个人觉得最好加一个取值的概念,就是把值取出来什么意思呢?

    比如上面的代码,本身a是等于10,然后进行a++,这个时候我们将a的值取出来,因为a最开始也就是原始值就是10,所以取出的a就是10,再把这个a赋值给b,之后再将a加一,对于++a我们是先将a的值进行加一,因为经过上一步骤的操作,a的值已经变成11了,此时再加一为12,然后再将a的值取出来就是12,再赋值个c。

    为什么要多说一个取值的概念,我们来看一道题你就明白了
    这里写图片描述

    你知道这道题的答案吗?

    小白:这个,还真是有点晕呢?

    庆哥:如果你只是知道先赋值再加一或者先加一再赋值的概念的话相信你这道题会有点晕,但是你如果还知道一个取值的概念那就容易多了,画个图看我给你分析一下

    这里写图片描述

    我们注意看红色我标注的数字,首先a是等于3的也就是初始值,然后执行a++,所以先将a的值取出来也就是3,然后加一是四,再执行++啊,因为此时a等于4,而++a需要先将a加一等于5再将a的值取出来也就是5,对于a*10那就是50了,所以结果就是58,怎么样,经过这样一分析是不是很简单

    这里写图片描述

    小白:确实啊,经过这样一分析真的感觉这道题很清晰,看来简单的“取值”俩字是相当重要啊。

    庆哥:那是,你可要记住了,关于自增和自减我们就说到这里了,接下来我们说一下赋值运算符吧!

    赋值运算符

    小白:赋值运算符是不是就是=号啊
    庆哥:其实也就是,=是最基本的赋值运算符,但是相信你肯定也见过类似+=和-=之类的,这个是赋值运算符的扩展,其实也很好理解,对于最基本的赋值运算符我觉得不用说,而这些扩展的赋值运算符我举一个例子也就懂了

    这里写图片描述

    这个b += a意思就是先把b和a的值相加再赋值给b。

    小白:那么对于其他的是不是一样的道理,举一反三即可

    庆哥:聪明,那我们赶紧再来看看比较运算符

    比较运算符

    小白:这个比较运算符是不是就是== ,>=,<=还有什么>和<或者!=啊

    庆哥:是的,比较运算符就是这些东西,其实蛮简单的,我们只需要记住一点那就是这个==,当比较的是数字的时候就是在比较上方大小,但是如果==两边是对象引用则比较的是对象的内存地址,这点我们要注意了

    小白:嗯嗯,这点我知道,我其实对&&和||这个玩意有点晕,咱赶紧讲讲这个吧!

    逻辑运算符

    庆哥:那行,你说的这些是逻辑运算符,首先我们要清楚有哪些逻辑运算符
    & 这个叫做逻辑与
    | 这个叫做逻辑或
    ^ 这个叫做逻辑亦或
    !这个叫做逻辑非

    然后还有两个这样的

    && 这个叫做短路与
    || 这个叫做短路或

    我们一个个来说,首先说一下这个逻辑与也就是这个符号“&”,这个逻辑与有并且的意思,也可以看成是一个and,我们看一段代码
    这里写图片描述

    经过以上代码我们可以得出一个结论那就是对于逻辑与,只有两边结果都是true结果才是true,否则都是false,另外你也需要知道对于逻辑运算符的执行结果只有两种结果那就是true或者false。

    以上就是我们逻辑与的用法了,记住了只有同时为真才是真,否则就是假,接下来我们再来看看这个逻辑或也就是“|”

    经过逻辑与的学习对于逻辑或我们就应该明白了,那就是只要两边有一个结果是true那结果就是true,换句话说就是只有两边同时为false结果才是false,其他都是true。

    这个就不做什么代码演示了,很简单。接下来精炼两句话

    对于逻辑与,有false则false
    对于逻辑或,有true则true

    接下来我们再来看看逻辑亦或也就是“^”,这个是什么意思呢,看一段代码就明白了

    这里写图片描述

    从得出的结果我们可以看出,对于逻辑亦或,只要两边结果相同就是false,两边不同就是true。

    那么对于逻辑非你觉得还需要说吗?

    小白:逻辑非是不是就是非真即假,非假即真

    庆哥:说的相当到位,接下来我们的重点要放在短路与或也就是&&和||,那么这两个什么意思呢?以及它们与逻辑与和或有什么区别呢?

    其实这个也好理解,我们看&&和||叫做短路与或,什么是短路呢?我们之前学物理中知道,发生短路也就造成堵塞效果,这里的意思就是,对于&&而言,如果左边的结果是false的话,右边的就不再进行判断,结果直接为false,而对于||而言,如果左边的结果为true的话,右边的就不再执行,结果就是true,你说为什么要这样呢?也就是说&&和||与&和|有什么区别呢?

    小白:这里有一个疑问,他们的执行结果应该都是一样的吧,这样的话觉得短路与或的执行效率会更加高一些

    庆哥:完全正确,对于&&和&或者||和|,他们的执行结果是完全一样的,不同点就是一个短路效应,从性能上短路与或提高了执行效率。其实在位运算符中也有&和|,我们再来看看这个位运算符

    位运算符

    庆哥:其实对于位运算符我们平常使用的并不是很多,所以这里我们把最重要的结论性知识告诉你,首先在位运算符中

    &叫做位与
    |叫做位或
    ^叫做位亦或

    其实对于位运算符还有~和<<<等,这些真的不常用,所以这里就不再说了我们就来说一下这个位与或和亦或。

    我们首先要知道对于位运算符操作的实际上都是二进制,我们先记住一下几个规则

    & 有0则0
    | 有1则1
    ^ 相同则0,不同则1

    什么意思呢?我们举一个例子来看看

    这里写图片描述

    我们猜这个结果是什么,答案是

    这里写图片描述
    注意这里可不是6除以3,它是这样计算的,首先6和3都要转成二进制,6的二进制是110,3的二进制是11也就是011,那么这样运算
    这里写图片描述

    我相信看图就能明白的,而二进制的010就是2啦,这就是位与的操作,对于或和亦或同样道理,规则上面也说了

    小白:晓得了,原来是这样,不过这个好像要知道进制是如何转换的吧

    庆哥:是的,关于进制转换也是个基础知识,也很有必要掌握一下,改天一起学习下,接下来我们就来说说这最后的三目运算符

    三目运算符

    庆哥:你知道什么是三目运算符吗?

    小白:这个三目运算符是不是就是这样的形势啊

    这里写图片描述

    庆哥:可以啊,看来不用讲了,就是这样的,其实这个三目运算符就是if-else的代替,我们就以你这个例子说一下吧,注意这种形式,首先是一个表达式,通常结果是true或者false,然后后面跟着一个问好,紧接着是两个数值用分号隔开,我们看这个,5大于3这是true,那么我们就把问号后面的第一个数值赋值给a,否则就把第二个数值赋值给a,这应该很好理解吧!

    正规来说三目运算的一个表达式如下:

    (关系表达式)?(表达式):(表达式)

  • 相关阅读:
    IO流中文件和文件夹的删除程序举例
    2.14 小结
    mysql数据库分库分表(Sharding)
    django 连接mysql
    网页页面自动刷新代码
    python you-get 下载视频
    爬虫米扑代理
    python urlretrieve 下载图片
    UnicodeDecodeError: 'gbk' codec can't decode byte 0xae in position 120: illegal multibyte sequence
    create a bootable USB stick on Ubuntu
  • 原文地址:https://www.cnblogs.com/ithuangqing/p/12113665.html
Copyright © 2011-2022 走看看