第一题 char运算后的数据类型
最后输出的是什么类型?
答案:int
char与byte的联系和区别
- char是无符号型的,能够表示一个整数,不能表示负数(0~65535);而byte是有符号型的,能够表示-128—127 的数;
- char、byte、int对于英文字符,能够相互转化
public static void main(String[] args) {
char a = 'a';
int aa = 97;
System.out.println(a == aa);
byte bb = 'b';
int cc = 'c';
char b = (char)98;
char c = (char)99;
System.out.println("bb:"+bb);
System.out.println("cc:"+cc);
System.out.println("b:"+b);
System.out.println("c:"+c);
}
- char可以表示中文字符,byte不可以。(一个字占2个字节)
题目解释
char类型的数据参与运算的时候,已经变成了byte,所以最后打印的一定是一个数字,但是为什么会变成int呢?
要理解这一点,我们需要两个前置小知识
前置小知识1
高级语言不管有多少数据类型,最终运行都要转换为C的6种数据类型
Java代码最终会变成C代码运行,而C中是没有Java的boolean类型和byte类型的
所以这两种类型,实际在CPU中运行的时候会变成其他类型
那具体会变成什么类型呢?int,原因请看前置知识2
前置知识2
CPU当中高速缓存的基本存储单位是缓存行,一个缓存行64Byte
缓存行通过导线和CPU相连,与CPU交互时要使用高低电压传输0101的bit信号
因为使用电压传输,电压是一种电势能,就不能同时传输(电势能叠加会抵消),只能排队
所以当一个缓存行中的数据数量越多,读写的时候排队的概率越大,排队等待的时间越长
反之,数据数量越少,则拥塞程度越小,读写的时候排队的概率越小,排队等待的时间越短
所以,小存储的数据类型少用,大存储的数据类型多用,就可以降低排队时间,提高读写速度
Java底层就采用了转化机制,去提高读写速度
Java底层的boolean和byte都使用int类型表示,而不用short或者byte,就是为了提高缓存行的读写速度,所以是4字节
这里用到了一种思想:用空间换时间,操作系统很多时候都用了这种思想
结论
byte参与运算的时候,类型就会变成int
第二题 位运算
public static void main(String[] args) {
int a = -4;
int b = 5;
System.out.println(a & b);
System.out.println(a | b);
System.out.println(a ^ b);
System.out.println(a << 2);
System.out.println(a >> 2);
System.out.println(a >>> 2);
}
各自输出多少?
答案:
4
-3
-7
-16
-1
1073741823
讲解
计算机底层,数据的存储+运算都是用补码完成的
正数的原码,反码,补码相同
负数的补码 = 反码(符号位不变,其余位按位取反)+1;
&运算
只要不是全1(全是true),那么就是0(false)
|运算
只要有一个是1,就是1;全是0才是0
算出来是一个负数,我们刚才说了,计算机底层,数据的存储+运算都是用补码完成的
既然是负数,我们需要求它的原码
负数的原码 = (补码-1)+除符号位按位取反
^运算
异或运算,只要不一样就是1,一样才是0
算出来依然是一个负数,我们操作同上
<<运算
逻辑左移,不需要画图运算,因为是低位补零,所以一定是乘以2^n
左移两位,就是乘4,所以结果是-16
>>运算
逻辑右移运算,高位补符号位,也不需要我们画图,一定是除以2^n
右移两位,就是除以4,结果是-1
>>>运算
无符号右移,高位补0,低位舍弃,符号位参与运算,需要画图
>>>运算符将int和long视为32位和64位无符号整数类型,这是Java语言所缺少的。
将它右移2位,高位补零,就会变成正数
所以最后的结果是2^30-1 = 1073741823
第三题:字符串常量池
public static void main(String[] args) {
String str1 = "hello"; // 字符串常量池
String str2 = "he" + new String("llo");// 修改llo的内存空间为hello
System.out.println(str1 == str2);
}
输出结果是?
答案:false
讲解
str1,由于不是new出来的,所以存储在字符串常量池当中;
str2中的llo是new出来的,所以存在在堆当中
Java中的字符串相加,两个字符串只要有一个存储在堆中,拼接之后的最终结果也存储在堆中
通过关键字new定义:
1. 编译程序先在字符串常量池查找,是否存在"hello"常量。如果不存在,则在字符串常量池开辟一个内存空间,存放"hello";如果存在,则不另外开辟空间,保证字符串常量区只有一个"hello",节省空间。
2. 然后在堆区,开辟一个空间,存放new出来的String对象,并在栈区开辟空间,存放变量名称str1,str1指向堆区new出来的String对象。
直接定义:
1.在字符串常量区查找是否存在"hello"常量,如果不存在,则在字符串常量区开辟一个内存空间,存放"hello";
2.如果存在,则不另外开辟空间;在栈区开辟空间,存放变量名称str2,str2指向字符串常量池"hello"的内存地址。
参考文章:
java的字符串存储在堆中还是常量池中