记录自己学习的零散知识点。
java文件里面如果有公开类,类名必须与文件名一致。
不然javac命令会出错,javac 是java compile,将源文件编译成class文件
java的数据类型:
整型,byte,short, int, long, 分别对应1,2,4,8个byte的大小。缺省整形是int。
浮点型,float,double,分别对应4,8个byte的大小。缺省浮点型是double。double精度是float的两倍。
整形和浮点型值域都包含正负。
布尔型,占用1个byte,true,false。
字符型,占用2个byte,单引号,不能有两个字符,字符串需要用双引号。
取模运算符%,负数可以取模,10%-2,与正数结果一致。负数可以被取模,-10%2,结果正负与被取模数一致。甚至小数也可以取模。
两个整形的除法结果还是除法,不会提升数据类型得到小数。
整数与浮点数的除法才会得到小数
逻辑运算符,&&与&的区别在于,&&会进行优化,在逻辑判断时只要满足一个,就省去其他运算。比如false&&(3<4), 第一个是false,根据&&规则,最终结果肯定是false,则(3<4)不会被计算机处理。
运算符优先级,等号最低,因为赋值是最后一步。布尔运算符优先级低于比较运算符,因为比较运算得到的结果就是布尔值;比较运算符优先级低于算术运算符,因为比较运算的值往往需要先进行算术计算。
以0开头的整数为八进制,以0x开头的整数为十六进制。
位移运算符,>>符号位不动,其余右移,符号位后面补0,带符号位右移。
>>>连符号位一起右移,无符号位右移。这里的有无符号位,个人理解是指将移位前的数字看成无符号,所以需要所有位一起移动。
<<左移一律向左移动,不考虑是否带符号位。
按位运算符与位移运算符,不会改变变量本身的值,即使是单元运算符,只有赋值才会改变。
位运算符实际用的比较多的,可能是做mask掩码。
变量先赋值再使用,可以这样理解变量是基于内存,如果不重新赋值,会错误的引用该内存上次保存的值。
intellij 联想psvm = public static void main(String[] args), sout = System.out.println()
数据自动类型转换,在算术运算或赋值时,两个不同数据类型一起操作会统一转换到高精度。
double > float > long > int >short > byte
char类型只可以转为int, 虽然char和short都是2个字节,但short包含了1个符号位,不足以转换,所以char应该转为int。
强制类型转换,主要用在自动转换会出问题的类型转换上,比如高精度往低精度转换。
数值计算要反正溢出,因为整数行均包含正负,可能出现正正为负。应该在选择整数型时对其可能的范围需要有大致了解,确定范围及大小不会在后续操作时超出。
字符集是字符的集合,charset,比如GBK,中文字符集。编码encoding,char本质就是一个整数,编码就是把数字映射到字符。这样利用不同的编码,会显示出不同的字符。
Java是用UTF-16编码的规格。\uXXXX代表Unicode编码的转义符。
字符串可以和任意类型做加法,会把值转成字符串,然后再合并。此时符合加法优先级。比如(“a+b=" + 10 +20)结果是a+b=1020
字符串不是java的基本数据类型,同时String不是保留字,可以当作变量。
Sting的加法不会改变原来的变量,只有赋值才会改变。
自增自减操作符会改变变量的值,而且分前加加(减减)和后加加(减减)。区别在于是先输出结果,还是先进行加(减)操作。a++ 与 ++a, 哪个在前面,先操作哪步。
大括号包围的算一个语句块,在语句块内部只有一条语句时,可以从简化的角度,省略大括号。
Intellij reformat code,可以自动将代码格式化,这样不用强迫自己的编码习惯。通过IDEA来实现代码整洁。
Do...while语句在while条件后要加分号,作为语句结束标记。
死循环的出现,注意循环条件的改变,是否存在无法触发退出机制的可能。
进行条件或循环判断时,多思考变量的边界条件,考虑周全。比如int整型变量,如果一直执行自增,会在某个临界点从正数变成负数。
switch是一整个语句块,其中各个case条件是公有一个switch语句块,所以不能出现变量重名这些。
switch除了int整型外,还可以使用String变量。
java以分号作为结束符,可以在语句中间增加任意多的空行进行换行。
数组是类型一致变量的集合。这点区别与python的列表和元组,可以将多个不同类型的变量混合在一起。因为python是弱类型的。(这句不知道是否解释正确)
对变量来说,实质是内存地址,赋值是在对应的内存地址写入新的元素。
而数组则是对应地址连续的一系列内存,这样才可以通过下标偏移的方式来进行数组元素的读取。而且数组名本身是另一个内存地址,该内存地址保存的是数组对应连续内存的首位地址。有些类似C语言的指针的指针。这样在读到数组名后,根据存储的值去找数组内存,比如35;如果再加上偏移量,a[1], 35+1=36, 该位置是数组的第二个元素,这也就是很多编程语言的数组下标都从0开始的原因,可以方便的查找数组元素。
通过a.length来获取数组长度,数组一段创建出来后长度就无法改变。
数组初始值,比如数值类型,是0;boolean类型,是false。
数组可以通过赋值来指向新的数组地址,如果没有数组名指向旧有的地址,那么无法再访问,相当于“消失”,但相应的内存还在被占用。猜测这里就存在内存回收,将没有指针指到的数组内存进行回收。
所有非基础类型的变量都是这样通过“指针的指针”来进行使用查询,而基本类型变量则是一层指针,直接到指针所指向的内存读取即可,变量名对应的内存并不会直接保存数据。这样可以将常量进行维护,比如两个相同的变量指向同一个常量。
int[] a = new int[10];
int[] b;
b = a;
这里先创建一个数组名a,指向一个10长度的数组内存,后面再让一个数组名b等于a,其实质作用是让b也指向原始的数组内存,而不是先指向a,再指向数组内存。
多维数组的长度*.length是指向第一维的长度。
可以将多维数组理解成数组变量的数组,也就是说可以单独改变多维数组第一维的值。