零 概述
本篇文章是读《Java编程逻辑》的笔记
第一部分 编程基础与二进制
第1章 编程基础
- 为了操作数据方便,定义了数据类型和变量;数据计算的过程中还需要进行流程控制,所以有了控制语句;为了减少重复代码和分解复杂操作,引入了函数和子程序的概念。
- 数据类型和变量
数据类型为了对数据归类,以便于理解和操作。Java的基础数据类型有4中大类型:
- 整数类型:有四种整型,byte/short/int/long,分别有不同的取值范围;
- 小数类型:两种float/double,有不同的取值范围和精度;
- 真假类型:boolean,表示真假。
基本类型也有对应的数组类型,数组表示固定长度同种数据类型的多条记录,在内存中联系存放。
- 内存在程序看来就是一块有地址编号的连续空间,数据放到空间之后为了方便查找和操作,需要给位置起个名字——用变量来表示这个概念。变量的变是指内存空间里面存的值是可变的。但是变量的名称不变,这个名称是程序员心中的内存空间的意义——应该是不变的,如果你一定要个age变量里面放身高的值也是可以的。
小结:变量就是给数据起名字,方便找不同的数据,值可以变但是含义不应该变。
- 赋值。赋值就是给变量对应的空间设一个值,注意给float赋值的时候加F或f,因为小数默认是double类型。
- 数组类型。数组的长度确定之后就不能变化了。数组有一个length属性,但是是只读属性。如果数组的初始值就不能再给长度,因为这样会让计算机无所适从。例如一下代码:
int [] a= new int[3]{1,2,3}
数组和基本类型不一样,基本类型占一块内存空间,而数组需要两块:一块用于存储数组内容本身——第一个值的内存空间,另一块存储内容位置。
- 数组的比较是判断两个变量指向的同一个数组,而不是判断元素内容是否一样。
- 逻辑运算符。
- 异或(^):两个相同为false,两个不同为真。
- 或(|)与短路或(||)、与和短路与(&&)的区别是短路的只要第一个根据第一个可以得出结果,就不会执行第二个。例如下面代码
int b=0;
boolean flag= true|b++>0;
int b=0;
boolean flag= true||b++>0;
第一段b最后结果为1,第二个最后结果为0。既第二个只要得出结果就不会求后面的。
- switch的类型为byte,short,int,char,枚举和String,为什么没有float、double和long呢?这和switch的实现原理有关。switch的转换和具体的系统实现有关。如果分支比较小,可能会转换为跳转语句,如果分支比较多,会转换为跳转表——跳转表高效的原因是其中的值必须为整数——String通过hashCode方法转换为整数,且按大小排序可以使用二分查找。如果值是连续的或者比较密集,跳转表可能会优化为一个数组。跳转表的存储空间为32位,所以不能使用long类型,存储不下;没有float和double是因为存储的是整数。
- 函数的主要目的是减少重复代码和分解复杂操作。定义函数只是定义了一段有这明确功能的子程序,但是本身不会执行,需要调用。
定义函数时声明参数,实际上就是定义变量,只是这些变量的值是未知的,调用函数时传递参数,实际上就是给函数中的变量赋值。 - 函数参数里面比较特殊的是数组类型和可变长度。数组类型赋值的时候赋值的是数组存储自身内容本身的空间,所以修改会影响外面。可变参数实际上是变为了一个数组。例如下面两端代码等同。
public static int max(int min,int ... a){
//anything
}
public static int max(int min,int [] a){
//anything
}
mac(0,new int[]{2,4,5})
可变参数简化了代码书写。
- 函数调用
函数调用是通过栈来存储相关的数据——变量和下一条执行语句等,系统就调用者和函数如何使用栈做了约定,返回值可以简单的认为是通过一个专门的返回值存储器存储的。从这个过程中可以看出,函数的调用是有开销成本的——分配额外的栈空间存储参数、局部变量以及返回地址,还需要进行出栈和入栈操作。所以函数大小的划分需要衡量。 - 数组和对象的内存分配
数组和对象的内存由两块组成,一块存放实际内容,一块存放实际内容的地址。存放实际内容的空间一般不分配在栈上,而是分配在堆上。存放地址的空间分配在栈上。
第2章 理解数据背后的二进制
- 二进制的最高位表示符号,1位负数、0位正数。但是二进制的实际表示方法是补码表示法,例如byte类型的-1:1的原码是00000001,取反是11111110,然后加1就是11111111。
知道了最高位为符号位,那么就可以推算出为什么byte的最大值为127,最小值为-128了。8位2进制的模为256,正数和负数各占一半,00000000到01111111表示正数,10000000到11111111表示负数。这个计算过程复杂,但是为了简单的记范围区间的算法-2n~2n -1。
关于这一点,网上大多数关于补码、反码的讨论都无法计算出-128,或者计算逻辑有问题,常见csdn的博客。本书作者也没有去说这一块,可以参考知乎文章,或者2.1.2 数的机器码表示,这里从起源到计算都论述到了。
- 为什么计算机无法精确表示0.1?因为计算机只能表示2n的和,例如0.5=2-1、0.75=2-1+2-2。如果不是特别追求精度,可以使用四舍五入等方法。如果追求精度可以转换为正数,求玩值之后再转回小数。
- 为什么叫浮点数?这是由于在二进制表示中,表示那个小数点的时候,点不是固定的而是浮动的。在十进制中表示123.45,直接这么写就是固定的。如果使用1.2345E2那就是小数点向左浮动了两位。二进制中表示小数也采用类似科学计数法,形如m*(2e),m称为尾数,e称为指数。在二进制中,单独表示尾数部分和指数部分,另外还有一个符号位表示正负。
几乎所有的硬件和编程语言表示小数的二级制格式是一样的——IEEE754标准。一种是32位(Java的float),一种是64位(Java的double)。32位格式中,1位表示符号,23位表示尾数,8位表示指数。64位格式中,1位符号、53位尾数、11位指数。Java中想查看浮点数的具体二进制形式,可以使用如下代码:
Integer.toBinaryString(Float.floatToIntBits(value));
Long.toBinaryString(Double.floatToIntBits(value));
- char本质上是一个占用固定两个字节的无符号整数——Java采用UTF-16BE编码,这个正整数表示Unicode编号,用于表示那个Unicode编号对应的字符。关于更多编码文章,可以看java中一个汉字占几个字符。
第3章 类的基础
- 类的属性和方法分为:类所有也叫静态,静态成员变量和静态方法;实例所有的变量和方法。
- 静态初始化代码块在类加载的时候执行,这是在任何对象创建之前,且只执行一次。
网友评论
非常感谢~~~