Fork me on GitHub

盘点java数值运算中的那些骚操作

标识符和关键字

java标识符必须由字母、下划线、数字、美元符($)组成,其中数字不能做开头。

  • 字母为Unicode字符集所支持的字符,包括但不限于中文字符、日本字符等。
  • 特殊字符只能包含美元符,其他字符如@、#等不行。
  • 严格区分大小写。
  • 不能含有空格。

java一共包含50个关键字(至java 8),均为小写。

mark

goto和const为保留字,至今仍未使用(java 8),但不代表以后不使用。

三个特殊直接量:true、false、null。

基本数据类型

整型

直接给出一个整数值默认为int类型。

  • 将一个较小的整数值(byte或short类型范围内)赋值给一个byte或short变量,系统自动将其当做byte或short类型处理。

    byte占一个字节,short占两个字节。

  • 将一个超过int类型的整数值赋值给long时,java不会自动将这个整数值当long类型来处理,必须得在后面加上L或l。

1
2
3
4
5
6
7
8
9
10
11
12
13
//java 7引入功能:在整型或浮点型数值中可以任意使用下划线分隔
//输入的是补码
int a = 0B1000_0000_0000_0000_0000_0000_0000_0011;
System.out.println(a);//输出-2147483645

int b = 0B1000_0000_0000_0000_0000_0000_0000_0011L;
System.out.println(b);//非法

long c = 0B1000_0000_0000_0000_0000_0000_0000_0011L;
System.out.println(c);//输出2147483651

long d = 0B1000_0000_0000_0000_0000_0000_0000_0011;
System.out.println(d);//输出-2147483645

字符型

char类型占两个字节。

三种表示形式:

  • 直接通过单个字符来表示:’A’、’9’、’0’等。
  • 通过转义字符表示特殊字符型值:’\n’、’\t’等。
  • 直接使用Unicode值来表示字符型值:’\uXXXX’,其中XXXX代表一个十六进制整数。

浮点型

java浮点型默认为double类型的值,若希望当成float类型处理需要加上f或F。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
float a = 5.2388858694f;
System.out.println(a);//输出5.238886

float b = 5.2388858694;
System.out.println(b);//非法

double c = 5.2388858694;
System.out.println(c);//输出5.2388858694

double d = 5.2388858694f;
System.out.println(d);//输出5.238885679516602(小数点第六位之后为随机输出)

float q1 = 5.6;
System.out.println(q1);//非法

float q2 = 5.6f;
System.out.println(q2);//输出5.6

float q3 = 5;
System.out.println(q3);//输出5.0

正无穷大通过Double类或Float类的POSITIVE_INFINITY来表示,负无穷大通过Double类或Float类的NEGATIVE_INFINITY来表示,非数用Double类或Float类的NaN来表示。

所有正无穷大都相等,所有负无穷大也相等,NaN不与任何数值相等,与其本身也不相等。

只有浮点数除以0才能得到正负无穷大,如果整数值除以0则会抛出异常:java.lang.ArithmeticException: / by zero(除以0异常)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
System.out.println(5.13 / 0);//输出Infinity
System.out.println(-5.13 / 0);//输出-Infinity
System.out.println(0.0 / 0.0);//输出NaN
System.out.println(0 / 0);//非法

double q = 0.0;
System.out.println(q/q == Float.NaN);//输出false

double s = Double.NEGATIVE_INFINITY;
float g = Float.NEGATIVE_INFINITY;
double m = Float.POSITIVE_INFINITY;
//float n = Double.POSITIVE_INFINITY;非法

System.out.println(Double.NaN == Float.NaN);//输出false
System.out.println(s == g);//输出true
System.out.println(s == m);//输出false
System.out.println(6.0 / 0 == 100.0 / 0);//输出true

自动类型转换

mark

当把任何基本类型的值和字符串值进行连接运算时,基本类型的值将会自动转换为字符串类型。

当一个算术表达式中包含多个基本类型的值时,整个算术表达式的数据类型将会发生自动提升:

  • 所有byte类型、short类型、char类型将被提升到int类型。
  • 整个算术表达式的数据类型自动提升到与表达式中最高等级操作数同样的类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String str1 = 2.5f + "";
System.out.println(str1);//输出2.5

String str2 = true + "";
System.out.println(str2);//输出true

System.out.println(3 + 4 + "Hello");//输出7Hello
System.out.println("Hello" + 3 + 4);//输出Hello34

System.out.println('a' + 2 + "Hello");//输出99Hello
System.out.println("Hello" + 'a' + 2);//输出Helloa2

short s = 5;
//s = s-2;非法
s = (short)(s-2);//合法
s -= 2;//合法
System.out.println(s);//输出1

强制类型转换

缩小转换会发生数据丢失:

1
2
3
4
5
byte a = (byte)0B11101001;
System.out.println(a);//输出-23

int b = 0B11101001;
System.out.println(b);//输出233

运算符

求余运算符和自加自减运算符均可以操作浮点型。

1
2
3
4
5
6
7
8
System.out.println(5.2 % 2.5);//输出0.20000000000000018
System.out.println(5 % 0.0);//输出NaN
System.out.println(0 % 5);//输出0
System.out.println(0 % 0.0);//输出NaN

float w = 4.3f;
w++;
System.out.println(w);//输出5.3

位运算符(7个)

1
2
3
4
5
6
7
8
System.out.println(5 | 9);//输出13
System.out.println(5 & 9);//输出1
System.out.println(~-5);//输出4
System.out.println(5 ^ 9);//输出12
System.out.println(5 << 2);//输出20
System.out.println(-5 << 2);//输出-20
System.out.println(-5 >> 2);//输出-2
System.out.println(-5 >>> 2);//输出107374182

以上均是对补码进行操作。

右移运算符>>:把第一个操作数的二进制码右移指定位数(第二个操作数指定)后,左边空出来的位用原来的符号位来填充。

无符号右移运算符>>>:把第一个操作数的二进制码右移指定位数(第二个操作数指定)后,左边空出来的位总是用0来填充。

移位运算原则:

  • 对于低于int类型的操作数总是先自动类型转换为int类型后再移位。
  • 对于int类型的整数a>>b,当b>32时,系统先对32求余,得到的结果才是真正移位的位数。
  • 对于long类型的整数a>>b,当b>64时,系统先对64求余,得到的结果才是真正移位的位数。

若移位没有发生有效位的丢失,则左移n位相当于乘以2的n次方,右移n位相当于除以2的n次方。

比较运算符

对于==和!=运算符,如果两个操作数都是引用类型,那么只有当两个引用变量类型具有父子关系时才可以比较,而且这两个引用必须指向同一个对象(不同对象)才会返回true。

逻辑运算符

1
2
3
4
5
6
7
8
9
10
11
12
System.out.println(!false);//输出true
System.out.println(5 > 3 && '6' < 10);//输出false

int x = 10;
if (5 > 4 && ++x > 10)
System.out.println(x);//输出11
if (5 > 4 & ++x > 10)
System.out.println(x);//输出12
if (5 > 4 || ++x > 10)
System.out.println(x);//输出12
if (5 > 4 | ++x > 10)
System.out.println(x);//输出13

对于短路逻辑或||而言,如果第一个数返回true,则不再对第二个操作数求值,直接返回true;而不短路或|总是执行前后两个操作数。

对于短路逻辑与&&而言,如果第一个数返回false,则不再对第二个操作数求值,直接返回false;而不短路与&总是执行前后两个操作数。

运算符结合的结合性与优先级

除单目运算符、赋值运算符、三目运算符是从右到左结合的,其他运算符都是从左到右结合的。

mark

-------------本文结束感谢您的阅读-------------
undefined