一、运算符简单认识
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
Java语言使用运算符讲一个或多个操作数连缀成执行性语句,用以实现特定功能。
Java语言中的运算符可分为如下几种:
算数运算符
赋值运算符
比较运算符
逻辑运算符
位运算符
类型相关运算符
二、运算符分类
1,算数运算符
Java支持所有的基本算数运算符。
(1)+:加法运算符
(2)-:减法运算符
(3)*:乘法运算符
以上代码示例:
int a1=5;
int a2=3;
System.out.println("加法运算:a1+a2="+(a1+a2));
System.out.println("减法运算:a1-a2="+(a1-a2));
System.out.println("乘法运算:a1*a2="+(a1*a2));
运行结果:
加法运算:a1+a2=8
减法运算:a1-a2=2
乘法运算:a1*a2=15
(4)/:除法运算符
除法运算符有些特殊:
a.如果除法运算符的两个运算数都是整数类型,则计算结果也是整数,就是将自然除法的结果截断取整,例如19/4的结果是4,
而不是5。并且 除数不可以是0,否则将引发除以零异常。
b.如果除法运算符的两个运算数有一个是浮点数,或者两个都是浮点数,则计算结果也是浮点数,这个结果就是自然除法的结果,
此时允许除数是0或者0.0,得到正无穷大或负无穷大。
代码示例:
//除法运算
double a=5.2;
double b=3.1;
double div=a/b;
//div的值将是
System.out.println(div);
//输出正无穷大:Infinity
System.out.println("5除以0.0的结果是:"+(5/0.0));
//输出正负穷大:-Infinity
System.out.println("-5除以0.0的结果是:"+(-5/0.0));
//下面代码将出现异常 java.lang.ArithmeticException:by/zero
System.out.println("-5除以0.0的结果是:"+(-5/0));
运行结果:
5除以0.0的结果是:Infinity
-5除以0.0的结果是:-Infinity
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Suanshu.main(Suanshu.java:20)
(5)%:求余运算符(取模)
求余运算的结果不一定总是整数,它的计算结果是使用第一个运算数来除以第二个运算数,得到一个整除的结果后剩下的值就是余数。
求余运算也进行了触发运算,所以:
a.如果求余计算的两个运算数都是整数类型,则求余运算的第二个运算数不能是0,否则引发除以零异常;
b.如果求余计算的两个操作数中有1个或者2个是浮点数,则允许第二个操作数是0或者0.0
,求余运算的结果是:NaN。0或0.0对零以外的任何数求余都将得到0或0.0.
代码示例:
double a=5.2;
double b=3.1;
double mod=a%b;
//mod的值是2.1
System.out.println(mode);
//输出非数:NaN
System.out.println("5对0.0求余的结果是:"+(5%0.0));
//输出非数:NaN
System.out.println("-5对0.0求余的结果是:"+(-5%0.0));
//输出0
System.out.println("0对5.0求余的结果是:"+(0%5.0));
//输出非数:NaN
System.out.println("0对0.0求余的结果是:"+(0%0.0));
运行结果:
2.1
5对0.0求余的结果是:NaN
-5对0.0求余的结果是:NaN
0对5.0求余的结果是:0.0
0对0.0求余的结果是:NaN
(6)++:自加,单目运算符
(7)--:自减,单目运算符
上述两个符号可以出现在操作数的左边或右边,出现在左边或右边的效果是不一样的。
a.如果把++(或--)放左边,则先把操作数加1(或减1),然后才把操作数放入表达式中运算。
b.如果把++(或--)放右边,则先把操作数放入表达式中运算,然后才把操作数加1(或减1).
代码示例:
int a=5;
//让a先执行算数运算,然后再自加
int b=(a++) +b;
System.out.println("a的值是:"+a";\nb的值是:"+b);
int i=5;
//先让a自加,然后执行算数运算
int ii=++a +6;
System.out.println("i的值是:"+i";\nii的值是:"+ii);
运算结果:
a的值是:6;
b的值是:11
i的值是:6;
ii的值是:12
注意:自加和自减只能用于操作变量,不能用于操作数值直接量或常量。例如5++、6--等写法都是错误的。
2,赋值运算符
赋值运算符:=
代码示例:
//为变量str赋值为JavaString str="java";//为变量pi赋值为3.14double pi=3.14;//为变量visited赋值为trueboolean visited = true;//将一个变量的值赋给另一个变量String str2=str;int a;int b;int c;//一次为多个变量赋值,不推荐这样写,因为这种写法导致程序的可读性降低。a=b=c=8;
&:按位与|:按位或^:异或,相同为0,不同为1~:取反<<:左移位>>:右移位>>>:无符号右移位
位运算符的运算结果表:
>>、>>>和<<三个移位运算符并不是适合所有的数值类型,它们只适合对byte、short、char、int、float和long等整数型进行运算。进行移位运算符有如下规则:(1)对于低于int类型(如byte、short和char)的操作数总是先自动类型转换为int类型后再移位。(2)对于int类型的整数移位a>>b,当b>32系统先用b对32求余(因为int类型在只有32为),得到的结果才是真正移位的位数。例如a>>33和a>>1的结果玩去哪一样,而a>>32的结果和a相同。(3)对于long型的整数移位时a>>b,当b>64,总是先用b对64求余(因为long类型是64位),得到的结果才是真正位移的位数。
赋值运算符可与算数运算符、位移运算符结合,扩展称为功能更加强大的运算符号。扩展后的赋值运算符如下:+=:对于x+=y;对应于x=x+y。-=:对于x-=y;对应于x=x-y。*=:对于x*=y;对应于x=x*y。/=:对于x/=y;对应于x=x/y。%=:对于x%=y;对应于x=x%y。&=:对于x+=y;对应于x=x&y。|=:对于x|=y;对应于x=x|y。^=:对于x^=y;对应于x=x^y。<<=:对于x<<=y;对应于x=x<<y。>>=:对于x>>=y;对应于x=x>>y。>>>=:对于x>>>=y;对应于x=x>>>y。代码示例:
//定义一个byte类型的变量byte a=5;//下面语句出错,因为5默认是int类型,a+5就是int类型。//把jin类型赋值给byte类型的变量,所以出错// a=a+5;//定义一个byte类型的变量byte b=5;//下面语句将不会出现错误b+=5;System.out.println("b="+b);运行结果:
b=10
比较运算符用于判断两个变量或常量的大小,比较运算符的结果是一个布尔值(true或false)。Java支持的比较运算符有:> :大于,只支持左右两边操作数是数值类型。如果前面变量的值大于后面变量的值,返回true。>=:大于等于,只支持左右两边操作数是数值类型。如果前面变量的值大于等于后面变量的值,返回true。<:小于,只支持左右两边操作数是数值类型。如果前面变量的值小于后面变量的值,返回true。<=:小于等于,只支持左右两边操作数是数值类型。如果前面变量的值小于等于后面变量的值,返回true。==:等于,如果进行比较的两个操作数都是数值型,即使它们的数据类型不同,只要它们的值相等,都将返回true。
例如97=='a'返回true,5.0==5也返回true。如果两个操作数都是引用类型,只有当两个引用变量引用的相同类的实例时才可以比较,而且必须这两个引用指向
同一个对象才会返回true。Java也支持两个boolean类型的值进行比较,例如true==false将返回false。!=:不等于,如果进行比较的两个操作数都是数值型,无论它们的数据类型是否相同,只要它们的值不相等,都将返回true。
例如97=='a'返回true,5.0==5也返回true。如果两个操作数都是引用类型,只有当两个引用变量引用的相同类的实例时才可以比较,只要两个引用指向
不是同一个对象就会返回true。代码示例://输出trueSystem.out.println("5是否大于4.0:"+(5>4.0));//输出trueSystem.out.println("5和5.0是否相等::"+ (5==5.0));//输出trueSystem.out.println("97和'a'是否相等:"+(97=='a'));//输出falseSystem.out.println("true和false是否相等:"+(true==false));//创建2个TEst对象,分别赋给t1和t2两个引用TEst t1=new TEst();TEst t2=new TEst();//t1和t2是同一个类的两个实例的引用,所以可以比较,但t1和t2引用不同的对象//所以返回falseSystem.out.println("t1是否等于t2:"+(t1==t2));//直接将t1的值赋给t3,即让t3指向t1指向的对象TEst t3=t1;//t1和t3指向同一个对象,所以返回trueSystem.out.println("t1是否等于t3:"+(t1==t3));运行结果:5是否大于4.0:true5和5.0是否相等::true97和'a'是否相等:truetrue和false是否相等:falset1是否等于t2:falset1是否等于t3:true
Integer a=new Integer(6);//输出trueSystem.out.println("6的包装类实例是否大于5.0:"+(a>5.0));//两个包装类实例比较。包装类的实例实际上是引用类型,只有两个包装类引用指向同一个对象时才会返回true。//输出falseSystem.out.println("比较2个包装类的实例是否相等:"+(new Integer(2) == new Integer(2)));
运行结果:6的包装类实例是否大于5.0:true比较2个包装类的实例是否相等:false
如下代码所示://通过自动装箱,允许把基本类型值赋给包装类的实例Integer ina=2;Integer inb=2;//输出trueSystem.out.println("两个2自动装箱后是否相等:"+(ina==inb));Integer biga=128;Integer bigb=128;//输出falseSystem.out.println("两个128自动装箱后是否相等:"+(biga==bigb));以上结果一个相等一个不相等,原因是什么?可以查看Java系统中的java.lang.Integer类的源代码,如下所示://定义一个长度为256的Integer数组static final INteger[] cache =new INteger[-(-128)+127+1];static{//执行初始化,创建-128到127的Integer实例,并放入cache数组中for(int i=0;i<cache.length;i++)cache[i]=new Integer(1-128);}从上面可以看出,系统把一个-128~127之间的整数自动装箱成Integer实例,并放入了一个cache的数组中缓存起来,如果以后把一个-128~127之间的整数自动装箱成一个Integer实例时,实际上是直接指向对应的数组元素,因此-128~127直接的同一个整数自动装箱成Integer实例时,永远都是引用cache数组的同一个数组的元素,所以它们全部相等;但每次把一个不再-128~127范围内整数值自动装箱成INteger实例时,系统总是创建一个Integer实例,所以出现程序中的运行结果。类似的还有String类。
&:不短路与,作用与&&相同,但不会短路。&&:短路与,必须前后两个操作数都是true才返回true,否则返回false。若第一个为false,则不再判断第二个|:不短路或,作用与||相同。||:短路或,只要两个操作数中有一个true,就返回true,否则返回false。若第一个true,则后面的条件不再判断!:非,只需要一个操作数,如果操作数为true,返回false,如果操作数为false,返回true。^:异或,当两个操作数不同时才返回true,如果两个操作数相同则返回false。代码示例://直接对false求非运算,将返回true。System.out.println(!false);//5>3返回true,‘6’转换为整数54,‘6’>10返回true,求与后返回trueSystem.out.println(5>3 && '6'>10);//4>=5返回false,‘c’>'a'返回true。求或后返回trueSystem.out.println(4>=5 || 'c'>'a');//4>=5返回false,‘c’>'a'返回true。求异或后返回trueSystem.out.println(4>=5 ^ 'c'>'a');运行结果:truetruetruetrue
对于|与||的区别:
//定义变量a,b,并为两个变量赋值int a=5;int b=10;//对a>4和b++>10求或运算if(a>4 | b++ >10){//输出a的值是5,b的值是11System.out.println("a的值是:"+a+" b的值是:"+b);}运行结果: a的值是:5 b的值是:11执行以上程序可以看到a5,b=11,这表明b++>10表达式得到了计算,但实际上没有计算的必要,因为a>4已经返回了true,
则整个表达式一定返回true。
//定义变量a,b,并为两个变量赋值int a=5;int b=10;//对a>4和b++>10求或运算if(a>4 || b++ >10){//输出a的值是5,b的值是11System.out.println("a的值是:"+a+" b的值是:"+b);}运行结果: a的值是:5 b的值是:10执行以上程序可以发现表达式d++>10没有获得执行的机会。因为对于短路的逻辑或||而言,如果第一个操作数返回true,
||将不再对第二个操作数求值,直接返回true。&与&&的区别与此类似:
&总会计算前后两个操作数,而&&先计算左边的操作数,如果左边的操作数为false,直接返回false,根本不会计算右边的操作数。
三目运算符:?:语法格式:(expression)?if-true-statement : if-false-statement;规则:
先对逻辑表达式expression求值,如果逻辑表达式返回true,则返回第二个操作数的值,如果逻辑表达式返回false,则返回第三个操作数的值。代码示例:String str=5>3 ? "5大于3" : "5不大于3";//输出"5大于3"System.out.println(str);三目运算符都是作为if else的精简写法。因此可以将上面代码替换成if else的写法,代码如下:String str2=null;if(5>3){str="5大于3";}else{str="5不大于3";}这两种代码的效果是完全相同的。
三目运算符和if else的写法区别于:if后的代码块可以有多个语句,但三目运算符是不支持多个语句的。
不要把一个表达式写的过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用()来控制表达式的执行顺序。