Java 基本数据类型及其运算
1. 整型运算
- 四则运算
对于整型类型,Java 只定义了带符号的整型,因此,最高位的 bit 表示符号位(0 表示正数,1 表示负数)。各种整型能表示的最大范围如下:
- byte:-128 ~ 127
- short: -32768 ~ 32767
- int: -2147483648 ~ 2147483647
-
long: -9223372036854775808 ~ 9223372036854775807
因此存在溢出情况,求解溢出情况只需要将具体的数换为二进制进行加减即可,如果最高位变为 1,则溢出之后的数又会变为负数
注:没有必要为了节省内存而使用 byte 和 short 进行整数运算, 范围太小,即使确定了在 byte 类型内,后期的各种与 int 的转换会使代码十分冗余,难以维护
int i = 0 while(i>0){// 不是死循环,因为会溢出变为负数 i += 1000; }
-
移位运算
在计算机种整数总是以 2 进制的形式存在
// 左移,包括符号位向左截断相应的位数,而右边用 0 补上 int shitNum = 15;//00000000 00000000 00000000 00001111 int shitNumLeft1 = shitNum << 1;//00000000 00000000 00000000 00011110 System.out.println(shitNumLeft1);// 移位之后在转换二进制的时候相当于多乘了一个 2,30 int shitNumLeft2 = shitNum << 2;//00000000 00000000 00000000 00111110 System.out.println(shitNumLeft2);// 移位之后在转换二进制的时候相当于多乘了两个个 2,60 int shitNumLeft28 = shitNum << 28;//11110000 00000000 00000000 00000000 System.out.println(shitNumLeft28);// 移位过多可能会造成负数 -268435456,也就是说左移运算用作乘 2 工具是有风险的 // 左移一个负数,带符号移位,可能会变正,但也是乘 2 shitNum = -15; int shitNumNevigateLeft = shitNum << 1; System.out.println(shitNumNevigateLeft);
左移相当于乘 2,符号位在截断范围内,可能会出现正负交替的情况,如果没有发生有效数位的丢失那么左移几位就相当于乘以几次 2,如果移动的位数大于 32 则先对 32 求余在移位余数(移 33 和移 1 一致),并且移位之后并没有改变原来的数,只是得到一个新数。注:观看以上看出左移是无法用作乘 2 工具的
// 正数右移就是除 2,最后会为 0,移出的截断,右边 0 补充 int shitNum = 15;//00000000 00000000 00000000 00001111 int shitNumRight1 = shitNum >> 1;//00000000 00000000 00000000 0000111 System.out.println(shitNumRight1);// 移位之后在转换二进制的时候相当于除一个 2,7 int shitNumRight2 = shitNum >> 2;//00000000 00000000 00000000 00000011 System.out.println(shitNumRight2);// 移位之后在转换二进制的时候相当于除两个个 2,3 int shitNumRight28 = shitNum >> 28;//00000000 00000000 00000000 00000000 System.out.println(shitNumRight28);// 移位过多可能会造成 0 // 负数右移也是除 2,但是最高位不动,最后为 -1,就是 >> 对于负数来说为不带符号位的右移 int n = -536870912; int a = n >> 1; // 11110000 0000000 0000000 00000000 <= -268435456 int b = n >> 2; // 10111000 0000000 0000000 00000000 <= -134217728 int c = n >> 28; // 10000000 0000000 0000000 00000001 <= -2 int d = n >> 29; // 10000000 0000000 0000000 00000000 <= -1 //>>> 为带符号位的右移,负数一旦带符号移位就变为正数,但本质绝对值可能不再是除 2 int n2 = -536870912; int a2 = n >>> 1; // 01110000 0000000 0000000 00000000 <= 1879048192 int b2 = n >>> 2; // 00111000 0000000 0000000 00000000 <= 939524096 int c2 = n >>> 29; // 00000000 0000000 0000000 00000111 <= 7 int d2 = n >>> 31; // 00000000 0000000 0000000 00000001 <= 1
右移相当于除 2,>> 符号位不再移动范围内,>>> 符号位在移动范围内,移动位数过多可能会为 0, 并且右移运算符种的 >> 一定可以用作除法的工具,而且效率高。 如果移动的位数大于 32 则先对 32 求余在移位余数(移 33 和移 1 一致),并且移位之后并没有改变原来的数,只是得到一个新数。
-
位运算
- 与运算,两 bit 同为 1 为 1
- 或运算,任意一 bit 为 1 为 1
- 非运算,01 互换
-
异或运算,两 bit 不同为 1,相同为 0
int i = 167776589; // 00001010 00000000 00010001 01001101 int n = 167776512; // 00001010 00000000 00010001 00000000 System.out.println(i & n); // 167776512
2. 浮点数运算
浮点数运算与整数运算相比只能进行四则数值运算,不能移位运算,位运算,浮点数的表示范围比整形还要大,但是在计算机内部浮点数无法精确的表示。也就是说浮点数的运算存在误差,因此判断两个浮点数是否相等一般采用差值小于某个一个很小的数
// 比较 x 和 y 是否相等,先计算其差的绝对值:
double r = Math.abs(x - y);
// 再判断绝对值是否足够小:
if (r < 0.00001) {// 可以认为相等} else {// 可以认为不相等}
注:整数除 0 时会报错,浮点数除 0 时返回特殊值
double d1 = 0.0 / 0; // NaN
double d2 = 1.0 / 0; // Infinity
double d3 = -1.0 / 0; // -Infinity
3. 布尔运算
boolean 永远只有 true 和 false 两种值
短路运算 && ||,值得一提的是三元运算符也是短路运算符,确定结果之后不会执行剩下的表达式
4. 字符字符串
在 Java 种字符和字符串是两种不同的类型
4.1char
基本数据类型,一个 char 保存一个 Unicode 字符,可以直接将字符赋给 char 变量,也可以转义字符 u +Unicode 编码值赋值,将字符赋给 int 类型就可以看到对应的 Unicode 编码。
关于 Unicode 编码介绍请看
char c = 'a';
char c = '\u0041';int unicodeVlaue = 'a';
4.2String
引用类型变量,String 具有不可变性,因为源码中用 final 修饰了 char[] , 因此二次对同一 string 变量赋值,其实是创建了新的字符串对象将引用直接替换了,原来的 String 对象将被垃圾回收机制回收。
String = "123";// 可以包含空格
String = "123 \"";//String 种用 ""标识字符串的开始结束,如果字符串本身包含", 就用 \",也有其他的转义字符
String message = "输出:";
int num = 9;
System.out.println(message + num);//+ 为字符串拼接,可以在多个字符串之间执行,也可以用字符串与其他任何类型进行拼接,形成新的字符串
引用类型变量的值可以为 null 值