温故而知新---Java(一)
学习不仅要学习新的东西,而且还要时不时的回过头捡漏...
本文参考老马说编程系列等文,在此推荐大家关注老马说编程系列文章
正文
基础知识
数据类型主要是为了对数据进行分类,方便理解和操作,在Java中,有如下基本数据类型:
- 整数类型:有四种整型 byte/short/int/long,内存空间分别占用1/2/4/8个字节
- 小数类型:有两种类型 float/double,,内存空间分别是占用4/8个字节
- 字符类型:char,表示单个字符,内存空间是占用2个字节
- 真假类型:boolean,表示真假
对象是一种基本数据类型、数组和其他对象组合而成的一个比较复杂的数据类型
内存可以直接理解成一个很长的数组,CPU可以直接定位到内存中的任何一个位置
变量的起源是由于将数据类型置于内存后,为了方便地找到和操作这个数据,给这个位置起的一个名字;所以叫变量,是因为它仅仅表示的是内存中的位置,这个位置存放的值是可以变化的
内存表示
一个基本类型变量,内存中只会有一块对应的内存空间。但数组有两块,一块用于存储数组内容本身,另一块用于存储内容的位置。
上图在进一步解释,就是我们经常说的,基本数据类型保存的是值本身,而引用类型保存的是值所在的位置
运算规则
运算时要注意结果的范围,使用恰当的数据类型。两个正数都可以用int表示,但相乘的结果可能就会超,超出后结果会令人困惑
int a = 2147483647*2; //2147483647是int能表示的最大值
a的结果是-2。为什么是-2我们暂不解释,要避免这种情况,我们的结果类型应使用long,但只改为long也是不够的,因为运算还是默认按照int类型进行,需要将至少一个数据表示为long形式,即在后面加L或l,下面这样才会出现期望的结果:
long a = 2147483647*2L;
另外,需要注意的是,整数相除不是四舍五入,而是直接舍去小数位:
double d = 10/4;
结果是2而不是2.5,如果要按小数进行运算,需要将至少一个数表示为小数形式,或者使用强制类型转化,即在数字前面加(double),表示将数字看做double类型,如下所示任意一种形式都可以:
double d = 10/4.0; double d = 10/(double)4;
在进行小数运算的时候,经常会出现一些很奇怪的值,比如执行
这是由于计算机底层对于浮点数(小数)表示并不精确导致的,归根到底都是由于2进制的原因
自增/自减是对自己做加一和减一操作,但每个都有两种形式,一种是放在变量后,例如a++, a--,另一种是放在变量前,例如++a, --a
1 int a = 0; 2 System.out.println(a++);//0 3 int b = 0; 4 System.out.println(++b);//1 5 int c = 0; 6 System.out.println(c--);//0 7 int d = 0; 8 System.out.println(--d);//-1
逻辑运算符具体有如下几种
- 与(&):两个都为true才是true,只要有一个是false就是false
- 或(|):只要有一个为true就是true,都是false才是false
- 非(!):针对一个变量,true会变成false, false会变成true
- 异或(^):两个相同为false, 两个不相同为true
- 短路与(&&): 和&类似,不同的是A&B,如果A是false还需在判断B是false,而A&&B,如果A是false,那么直接就是false
- 短路或 (||):与|类似,不同的是A|B,如果A是true还需在判断B是true,而A||B,如果A是true,那么直接就是true
补充
补码
二进制使用最高位表示符号位,用1表示负数,用0表示正数。但负数表示不是简单的将最高位变为1,比如:
- byte a = -1,如果只是将最高位变为1,二进制应该是10000001,但实际上,它应该是11111111。
- byte a=-127,如果只是将最高位变为1,二进制应该是11111111,但实际上,它却应该是10000001。
这种表示法称为补码表示法,而符合我们直觉的表示称为原码表示法,补码表示就是在原码表示的基础上取反然后加1。取反就是将0变为1,1变为0。为什么负数要使用补码的形式呢?这是因为补码在计算加减的时候能保证是正确的!
位移操作
-
左移:操作符为<<,向左移动,右边的低位补0,高位的就舍弃掉了,将二进制看做整数,左移1位就相当于乘以2。
-
无符号右移:操作符为>>>,向右移动,右边的舍弃掉,左边补0。
-
有符号右移:操作符为>>,向右移动,右边的舍弃掉,左边补什么取决于原来最高位是什么,原来是1就补1,原来是0就补0,将二进制看做整数,右移1位相当于除以2。
有的小数计算为什么是正确的
System.out.println(0.1f+0.1f); //0.2
System.out.println(0.1f*0.1f); //0.010000001
按照上面所说的,第一行应该不等于0.2才是正确的,但是为什么等于0.2呢?其实,这只是Java语言给我们造成的假象,计算结果其实也是不精确的,但是由于结果和0.2足够接近,在输出的时候,Java选择了输出0.2这个看上去非常精简的数字,而不是一个中间有很多0的小数。在误差足够小的时候,结果看上去是精确的,但不精确其实才是常态。如果真的需要比较高的精度,一种方法是将小数转化为整数进行运算,运算结束后再转化为小数,另外的方法一般是使用十进制的数据类型,这个没有统一的规范,在Java中是BigDecimal