Java基础语法冷知识
概述
本篇文章只罗列了我所知道的,基本不涉及类知识的一些不太容易被人知晓的冷知识。
不过其实这些知识大多对生产没有太大用处。
但是说不定哪天这些东西会帮助自己避坑呢?
在编程之前为什么需要配置环境变量?
exe和路径的爱恨情仇
环境变量path的作用
自己定义环境变量并引用
而为了方便今后jdk路径变更以及Java EE的使用,我们又将jdk的路径单独设置一个环境变量JAVA_HOME,然后path中填写JAVAHOME\bin就完事儿了。以后如果要变更路径,去改JAVA_HOME就行啦。
基础语法基本数据类型中的冷知识(基于64位系统)
基本数据类型与内存的纠缠
int a = 1;
int b = 1;
上面这行代码,a和b使用的是同一块内存空间。什么意思呢?看下图:
像"1"这样的基本数据类型的值,我们称为直接量。int b = 1;时,会先查找栈中是否存在直接量"1",如果找到了,那么直接使用这个直接量。
整数变量的赋值
我们都知道byte a = 1000; short b = 1000000之类的赋值会报错:不兼容的数据类型,从int到byte(short),因为byte和short太小了。
强转,不强转?
1.0和1.1的爱恨情仇
boolean a = 1.0F == 1.0;
boolean b = 1.1F == 1.1;
这句话莫得毛病,但是点小有问题:
基本数据类型的==比较,比的是数值;而引用类型比的是地址。
不然为什么1.0 == 1.0F是true呢?是吧,哈哈哈。
boolean类型有多大?
这个问题标准答案是:没有答案。
对,就是这样,因为JAVA官方没有指明一个boolean占多大内存。
但是大众普遍认为大小是1个字节,也不能算错吧。
但更合理的猜测,不应该是一个bit么?
自动类型转换的一个小知识
我们都知道,自动类型转换遵从小转大的原则。
但是你知道么,这个小转大,并不是完全指内存的大小。
比如最特殊的一个:long类型可以自动转换为float类型。
又有小老弟懵逼了,其实原因很简单。
long类型表示的范围是$-2^{63}$至$2^{63}-1$。
而float的表示范围大概是$\pm10^{38} \approx \pm2^{114}$。
明显float能表示的数字更大,所以能够自动转换。
当然,自动转换之后,也不可避免地会产生严重的误差。
强制类型转换如何取舍地?
byte a = 128;的结果是多少呢?
这就要涉及到强转的数值取舍了。
小学二年级的时候都学过,128转换为二进制为:0000 0000 1000 0000。
因为byte类型就1个字节,所以强转之后,肯定需要舍弃一半。
java在进行强制转换时,舍弃的是高位部分,所以a的值最终为:1000 0000。也就是-128。
变量初始值
以前一直以为基本数据类型始终会有一个初始值,后来试了试,结果试试就逝世。
直接上结论吧
类成员变量(包括静态的),无论是基础数据类型还是引用数据类型,在不初始化的情况下都有初始值。
基本数据类型除了char,其他的初始值都是0(或者0.0)。
char类型初始值是’’。而引用数据类型初始值统一为null。而方法中的局部变量,不论是基本数据类型,还是引用类型,只要不初始化,直接编译就报错。
也就是说,下面这段代码,打印结果是0。
如果把te.wa换成age,则直接编译报错。
public class VarTest {
int wa;
public static void main(String[] args) {
int age;
VarTest te = new VarTest();
System.out.println(te.wa);
}
}
运算符中的冷知识除以一个0.0试试
小学二年级就学过,java中除以0会报arithmeticExcetption。
那大家知不知道java能否除以0.0呢?
答案是可以说可以,也可以说不可以~
例如:
5 / 0.0的结果是infinity;
0 / 0.0的结果是NaN。
显然都不是一个正常的数字,所以我们肯定也不应该去除以0.0的哈。
赋值运算本身也会返回一个值
什么意思呢?
其实很(没)简(有)单(用)。
举个栗子:
int a, b;
a = b = 3;
这段代码执行完之后,a和b都被赋值为了3。
因为b = 3这个表达式的结果是3。
运算结果的类型
小伙伴们觉得下面这段代码执行完后,a等于多少?
byte a = 10;
a = a + 2;
结果等于:报错~哈哈哈,想不到吧。
其实这是JAVA编译器自动进行了优化处理。
因为byte的运算(算术运算、移位运算等)的计算结果被编译器自动转换为了int。
而int赋值给byte很显然是会报错的。
所以当我们真的想写这样一段逻辑的话,需要使用如下写法:
byte a = 10;
a = (byte)(a + 2);
或者!
还可以如下:
byte a = 10;
a += 2;
这就很骚了,原来a += 2;等价的不是a = a + 2;,而是a = (byte)(a + 2);。
同理,不光是+、也不光是short会有这种优化。
可以自行尝试一下其他地方是否也有如此特性。
如何高效(装逼)地运算i*4?
大家都知道java中的位运算效率是最高的。
因为计算机底层就是二进制,如果直接对二进制进行操作,java不需要再费精力去将变量与二进制进行转换。
所以要高效地运算,最好的方法就是采用位运算。
而移位运算符刚好就具备倍乘、倍除的特性。
byte类型的9,二进制为0000 1001。
左移一位,变为0001 0010,值为18。
不用怀疑,就是二倍。
同理,右移一位0000 0100,值为4。
也不用怀疑,就是整数/2的结果。
所以的所以,如何高效运算i*4?
答案是i = i << 2;。
当然,我劝大家可别在实际开发中这样写,坏处很明显:容易被打…好吧,其实是可读性太低。
并且如果除符号位的最高位是1,左移之后的结果就很迷了。