Java学习日记~2020年10月26日
基本数据类型
整数类型
整数类型有byte、short、int、long。在不同位数的操作系统占用不同的字节。在64位操作系统中,它们分别占1、2、4、8个字节。
小数类型
小数类型有float和double,在64位操作系统中分别占用4和8个字节。double的表示范围比float更大,精度更高。
真假类型
boolean直接使用true和false赋值,表示真和假。
字符类型
字符类型char表示一个字符,通常占用2个字节。
数组类型
数组类型和基本类型的不同之处
基本类型的变量在内存中只会有一块对应的内存空间。而数组它是有两块的,一块是用于存储数组内容本身,另一块用于存储内容的位置。
数组用两块空间的好处 : 假如一个数组A长度是3,另一个数组B长度是5。如果把B赋值给了A,让A去把对应的内存空间直接存储B对应的内容,那是肯定不够的。但是两块空间存储就会简单的多。当把数组B赋值给数组A的时候,A直接将指针指向B的位置,数组A原先的内存空间因为不再被引用则被垃圾回收器给回收。
数组的长度一旦被定义了就不可再变化了,但是可以让数组重新指向一个长度不同的空间。
条件执行实现原理
程序最终都是一条条的指令,CPU有一个指令指示器,指向下一条要执行的指令,CPU根据指示器的指示加载指令然后执行。指令大部分是具体的操作和运算,在执行这些操作时,执行完一个操作后,指令指示器会自动指向挨着的下一条指令。但是也有一些比较特殊的指令,也就是"跳转指令",这些指令会修改指令指示器的值,让CPU跳到一个指定的地方执行。
跳转的方法有两种:一种是条件跳转,还有一种那就是无条件跳转,无条件跳转自然就是直接进行跳转。if else实际上就会转换为这些跳转指令
switch的原理
在程序源代码中,case值排列不要求是排序的,但是编译器会自动排序。在switch中case的值可以是byte、short、int、char、enum、String。其中byte、short、int本身就是整数,char本质上也是整数、枚举也有对应的整数、String用于switch的时候也会转化成整数。
当分支比较多的时候,使用条件跳转会进行很多次的运算,效率比较低,因此就会使用一种更高效的方式,那就是跳转表。跳转表是一个映射表,存储了可能的值以及要跳转到的地址。由于case中的值都会被转化成整数,然后整数会按照大小排序,排序好后的整数在查找的时候则可以使用二分查找,这样效率是比较高的。如果说值是连续的,跳转表还会进行特殊优化,优化成一个数组,直接下标索引。即使值不是连续的,编译器也可能会优化成一个数组型的跳转表,没有就指向default分支。
二分查找算法
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
public static int Method(int[] nums, int low, int high, int target)
{
while (low <= high)
{
//取中间值
int middle = (low + high) / 2;
//如果找到了就直接返回
if (target == nums[middle])
{
return middle;
}
//没找到就判断是在左边还是右边然后折半进行查找,因此效率高
else if (target > nums[middle])
{
low = middle + 1;
}
else if (target < nums[middle])
{
high = middle - 1;
}
}
return -1;
}
为什么switch不可以使用long?
因为跳转表值的存储空间一般是32位,容纳不下long。
简单总结
条件执行的语法是比较自然和容易理解的,需要注意的是其中的一些语法细节和陷阱。它执行的本质依赖于条件的跳转、无条件跳转和跳转表。条件执行中的跳转只会跳转到跳转语句以后的指令。如果跳转到以前的指令就会形成循环。