算术运算符
种类: + - × / %
% 结果± 由被除数决定
int x=-8;
int y=-4;
int r=x/y; //结果为2
y=5;
int r=x%y; //结果为-3
x=8;
y=-5;
r=x%y; //结果为3
x=5;
y=2;
r=x/y; //结果为2,结果取决于被除数和除数的数据类型
double r1=5.0/2; //结果为2.5
从上面程序中可以看出,当两个整数进行除法运算时, 如果两个操作数都是整数类型,则计算结果也是整数,得到的结果将是把小数部分截断取整后的整数。
但如果除法运算符的两个操作数有一个是浮点数,或者两个都是浮点数,则计算结果也是浮点数,这个结果就是自然除法的结果。而且此时允许除数是 0, 或者 0.0,分别有以下三种情况:
- 任意整数/0 抛出异常ArithmeticException
- 任意非零数字/0.0 任意非零小数/0.0
double r1=3.0/0.0
//结果为Infinity - 0/0.0 ->结果为NaN
0.0/0.0 ->NaN
0.0/0 ->NaN
//保留小数的两种方法
double d=45.127456;
System.out.println(String.format("%.2f", d));
DecimalFormat df=new DecimalFormat("0.00");
System.out.println(df.format(d));
String str=df.format(d);
//把String类型的变量转换成double类型变量
//若转换为int类型的变量:Integer.parseInt();
double d2=Double.parseDouble(str);
System.out.println(d2);
连接符:
+不仅可作为加法运算符使用 ,还可作为字符串连接运算符使用 。
/*与字符串相连的是连接符。
字符串在前,后面的都视为连接符
*/
System.out.println(3+5+""); //结果为8
System.out.println(""+3+5); //35
System.out.println(3+""+5); //35
运算符-赋值
赋值运算符的左边必须是变量,右边可以是变量,常量,表达式
r=x;
r=x+3; //表达式
r=(x=x+5); //表达式
x+3=r; //error
赋值方向:右到左赋值
强制转换,自动提升
强制转换:赋值运算符右边得比左边的大,需要强制转换
在变量或表达式前边添加(强制转换的类型).
强制类型转换类似于把一个大瓶子里的水倒入一个小瓶子,容易溢出
//直接把 5.67 赋值给 f1oat 类型变量将出现错误, 因为5.67 默认是 doub1e 类型
float a = 5.67 //error
float f0=(float)5.67; //5.67
int r0=(int)(3.0+3); //6
byte,short,int,long,char,float,double 和父子关系的类可强制转换
int iValue = 233;
// 强制把一个 int 类型的值转换为 byte 类型的值
byte bValue = (byte)iValue;
// 将输出 -23
System.out.println(bValue) ;
double dValue = 3. 98 ;
// 强制把一个 double 类型的值转换为 int 类型的值
int tol = (int)dValue ;
// 将输出 3
System.out.pr工ntln(tol);
在上面程序中,把一个浮点数强制类型转换为整数时, Java 将直接截断浮点数的小数部分。 上面程序还把 233 强制类型转换为 byte类型的整数,从而变成了 23 , 这就是典型的溢出 。 图 3.11 示范了这个转换过程。
从图 3.11 可以看出, 32 位 mt 类型的 233 在内存中如图 3.11 上面所示,强制类型转换为 8 位的 byte类型,则需要截断前面的 24 位,只保留右边 8 位,最左边的 1 是一个符号位,此处表明这是一个负数,负数在计算机里是以补码形式存在的,因此还需要换算成原码。
将补码减 1 得到反码形式,再将反码取反就可以得到原码。
最后的二进制原码为10010111. 这个 byte 类型的值为一(16+4+2+1),也就是 23。
字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。包装类都提供了一个 parseXxx(String str)静态方法用于将字符串转换成基本类型。若转换为int类型的变量:Integer.parseInt();
自动提升:赋值运算符右边的比左边的小,小的自动提升。
自动类型转换的类型如图1所示。
规则:
1.所有的 byte 类型、 short 类型和 char 类型将被提升到 int 类型。
2.整个算术表达式的数据类型自动提升到与表达式中最高等级操作数同样的类型
图片有点丑,尽力了哈哈~
下面程序示范了自动提升。
// int 类型可以自动转换为 float 类型
float f=6; //6.0
int i='a'; //97
byte b1=1;
byte b2=1;
byte r=1+1; //常量2
//法则:有变量参与的运算,表达式最小的数据类型为int
//表达式中的b1 和b2 将自动提升到 int 类型,则右边的表达式类型为 int
// 将一个 int 类型值赋给 byte 类型变量将发生错误
byte r2=b1+b2; //error
//法一
int r2=b1+b2;
//法二
byte r3=(byte) (b1+b2);
float f=4.5f;
// 右边表达式中最高等级操作数为double 类型
// 则右边表达式的类型为 double 类型, 故赋给一个 double 类型变量
float f5=f+3; //7.5
//典型案例
b2+=1; //b2=(byte)(b2+1)
b2=b2+1; //error
溢出、越界时,最大值加1等与最小值,最小值-1=最大值
byte b8=127;
byte r7=(byte)(b8+1); //-128
byte b9=-128;
byte r8=(byte)(b9-1); //127
自增自减运算符——> ++(–)
++(–)
前置 ++x :先自增,后赋值
后置x++:先赋值,后自增
int x=1;
int r=++x; //x=2,r=2
x=1;
int r=x++; //x=2,r=1
int i=6;
int j=i++ + ++i;
System.out.println(j+","+i); //14,8
i=6;
j=++i + i++;
System.out.println(j+","+i); //14,8
比较运算符
< >= <= == !=
boolean b=4>x>1; //error
逻辑运算符 && || !
(&&和||)有短路 (&和|)没有短路
&与&&的区别: &总会计算前后两个操作数,而&&先计算左边的操作数,如果左边的操作数为 false,则直接返回 false,根本不会计算右边的操作数。
true & 3>4 //两边是布尔类型,逻辑与
2 & 3 //位运算符
&&短路:左边返回false,表达式短路,右边不执行
||短路:左边返回true,表达式短路,右边不执行
int x=2,y=3;
boolean b=x++>3 && y--<1; //b=false x=3 y=3
如果&&前面有||,那么||左边返回true,导致短路
int x=1;
int y=1;
boolean b1=x++>0 || true && y++>0; //b1=true,x=2,y=1
boolean b2=x++>3 || true && y++>3; //b2=false,x=2,y=2
位运算符:二进制运算 (补码)
此处重点学 & | ^ ~
Java 支持的位运算符有如下 7 个。
&: 按位与 。当两位同时为 1时才返回 1 。
|: 按位或。 只要有一位为 1即可返回 1 。
~: 按位非。 单目运算符,将操作数的每个位(包括符号位〉 全部取反。
^:按位异或。 当两位相同时返回 0, 不同时返回 1。
<<:左移运算符。 >>: 右移运算符。 >>>: 无符号右移运算符。
做运算是补码运算,正数的原码补码反码都一样,按八位看,第一位是符号位,为0则为正数,负数的补码是其反码加 1
补码变原码:符号位不变,将补码-1,在取反
两个数交换的解决方案(3种):
int x=1,y=2;
//法一:中间变量
int a=x;
x=y;
y=a;
//法二:变量相加
x=x+y;
y=x-y;
x=x-y;
/*法三:异或
规则:i^i=0 i^0=i a^b^b=a
*/
x=x^y;
y=x^y; //y=x^y^y
x=x^y; //x=x^y^x
赋值运算符
+= -= *= /= %=
int i = 4;
i += 5; -> i=i+5;
三元运算符
A?a:b if(){} else{}
结果的数据类型:和a,b相关
String r2 = true?"a":"b"; //结果为a
Object r = true?"hello":23; //结果为hello
//因为Object是共同的父类,所以结果类型为Object
double r3=3<9?5:4.5; //结果为5.0
//整个表达式最高的数据类型为double类型,所以结果为double类型
equals与==的区别以及自动封箱、拆箱 :
- 自动封箱:把基本数据类型封装为此类型的封装类类型
- 自动拆箱:把对象里面的数值转成基本数据类型
- equals比较值大小,==比较内存地址
Integer i=23; //jdk版本高的,会将23自动封装成Integer类(自动封箱)
Integer i2=new Integer(2);
Integer i3=new Integer(2);
System.out.println(i2.equals(i3)); //结果为true 因为equals比较值大小
System.out.println(i2==i3); //结果为 false 因为“==”比较内存地址
Integer i4=22;
System.out.println(i==i4); //false 因为内存地址不同
Integer i5=23; //true 因为指向同一个内存地址
System.out.println(i2+i3); //4
//底层为这样:
System.out.println(i2.intValue()+i3.intValue()); //4 虚拟机自动完成的(自动拆箱)