Java的运算符
Java语言支持如下运算符
-
算数运算符:+, -, *, /, %(取模,和数学不一样,在计算机里取模一般就是取余数的意思), ++, --
二元运算符:+, -, *, /, %
public static void main(String[] args) {
//二元运算符
//Ctrl + D :赋值当前行到下一行
int a = 10;
int b = 20;
int c = 30;
int d = 40;
System.out.println(a+b);
System.out.println(a-b);
System.out.println(a*b);
System.out.println(a/b);//输出结果为0,不符合10/20=0.5的结果,因为a,b都是int类型,所以结果为int类型,取整数部分
System.out.println(a/(double)b);//正确写法,输出结果为0.5,把一个数据强转为double类型,计算结果也为double类型
}不同数据类型之间的二元运算和数据类型的转换关系
//二元运算符:+,-,*,/,%
public static void main(String[] args) {
long a = 123123123123123123L;
int b =1111111111;
short c=32767;
byte d=100;
int e = 10;
int f = 23;
System.out.println(a+b+c+d);//123123124234267101 为long类型,以为abcd中有一个是long类型,所以他们运算后的结果为long类型
System.out.println(b+c+d); //1111143978 为int类型,因为bcd中b为int类型,所以他们运算后的结果为int类型
System.out.println(c+d); //32867 超出了short类型的取值范围(-32768~+32767) 即为int类型,
/*在java运算中,在涉及到数据类型范围小于int的(如byte,char,short)时,
数据类型会自动提升为int类型,比如,两个byte类型的数据在进行运算时,
运算结果就会变成int类型,如果要结果是byte类型的话,就要强转成byte类型,
这是因为java编译器内部对其进行处理。*/
System.out.println(f%e); // 3,对23除以10进行模运算,取模23除以10的余数
System.out.println(e/(double)f);//0.43478260869565216 除法运算,因为结果是小数,所以要将其中一个数强转为double
System.out.println(e*f);
}一元运算符:++, --. 以及相关题目:
//一元运算符: ++(自增) --(自减)
public static void main(String[] args) {
int a = 3;
int b = a++; //先执行 b = a 再执行a=a+1
int c = ++a; //先执行a=a+1 在执行b = a
System.out.println(a); //5
System.out.println(b); //3
System.out.println(c); //5
//在进行关系运算的时候也要注意++的位置,仍然符合上述
int p = 5;
int q =5;
System.out.println(p++>5); //false(先执行p>5的判断,在执行p+1)
System.out.println(++q>5); //true(先执行q=q+1,在执行q>5的判断)
int s = a+c+b;
//常见的面试题
int e = 2;
int d = a++ + ++e; //这里a已经进行过两次++运算,所以a=5,则这里相当于a+(e+1)=5+(2+1)=8
int f = a-- - --e; //--同++道理一样,这里相当于a-(e-1)=5-(2-1)=4
System.out.println(d); //8
System.out.println(f); //4
//++常用语for循环语句,快捷键fori
for (int i = 0; i < 20; i++) {
s=s+c+b;
}
System.out.println(s);
//幂运算
//如何计算2^3,java中幂运算不能写成2^3这种形式,可借助一些工具类,如Math
double pow = Math.pow(2, 3); //Math.pow是幂运算 (pow为Power operation第一个单词的缩写)
System.out.println("2^3="+pow);
double abs = Math.abs(-3.1415926);//Math.abs是求绝对值(abs为absolute(绝对的)的缩写)
System.out.println("|-3.1415926|="+abs);
} -
赋值运算符:=
-
关系运算符:>, <, >=, <=, ==, !=, instanceof
(instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例),用法为:
boolean result = obj instanceof Class
//关系运算符,
public static void main(String[] args) {
//关系运算符返回的结果:true(正确) or false(错误)两种结果,
// 即返回值的数据类型一定是boolean类型(布尔值)
//所以关系运算符常与判断语句 if(){}一起使用
int a = 10;
int b = 20;
String name = "sss";
String name2 = "sss";
Integer c = 12121;
Integer d = 12121;
System.out.println(a>b); //false
System.out.println(a<b); //true
System.out.println(a==b); //false 判断是否相等(实际上是判断内存中的地址是否相等)
System.out.println(a!=b); //true 判断是否不相等(实际上是判断内存中的地址是否不相等)
System.out.println("================");
System.out.println(name==name2); //true,//为什么用String这个类定义的字符串也能用 == 来进行比较呢?
System.out.println(name!=name2); //false //Java中String有常量池,如果已经存在,就不会再创建同样的字符串常量了(new的不算)
System.out.println(name.equals(name2));//true//用equals()比较是比较的对象内容的值是否等价,
// 所以类创建的或者new的对象应该用equals()比较
/**关于String类型用==比较有时结果是对的的原因见Demo04
*{@link Demo04}(@link是一个个javadoc注解,可以指向一个类或者方法,按Ctrl点击类名可直接访问指定类)
* **/
System.out.println("=================");
System.out.println(c==d);
System.out.println(c!=d);
System.out.println(c.equals(d));
System.out.println(c);
System.out.println(d);
}Demo04:
public class Demo04 {
public static void main(String[] args){
String s1="a1";
String s2="a1";
String s3 = "a"+"1";
String s4 = "a"+1;
String s5 = "a"+Integer.parseInt("1");
int i = 1;
String s6 = "a"+i;
System.out.println(s1==s2);//true 很好理解,常量池
System.out.println(s1==s3);//true 还能理解,常量运算,值确定
System.out.println(s1==s4);//true 同上
System.out.println(s1==s5);//false 有点难以理解吧,这不跟上面一样吗?
//还真不一样,因为调用方法后的值只有在运行后才能确定
System.out.println(s1==s6);//false 解释上面,这样就好理解了
//不确定的值运算要存储结果吧,
//所以就分配空间了,与最上面true的情况就不同了
}
/*都知道String比较要用equals方法来比较其内容,用==比较的是两个对象的地址值,但上面的程序运行结果好像不是那么回事呢?
Java中String有常量池,如果已经存在,就不会再创建同样的字符串常量了(new的不算)
这样s1==s2就很好理解了,都指向常量池中同一个对象,地址当然一样了
s3和s4虽然+了一个不一样的值,但都是常量运算,编译期间就知道结果了,是一个定值,所以结果也指向了同一个常量池中的对象
s5不是也加了一个1吗,不是和s4一样的吗?结果为什么不同呢?加了一个1???真的是吗?确实是呀,没错,你看到的确实是,
但我们的程序运行的,paseInt方法只有在运行后才可能知道结果,运行后计算结果,就需要给参与运算的数据分配存储空间,
运算结果也要存起来,自然不是指向常量池里的那个对象了(理解的如有错误还请指正)
s6与s5类似,只有在运行时才能确定具体的值*/
} -
逻辑运算符:&&(与), ||(或), !(非)
public static void main(String[] args) {
//与(and) 或(or) 非(NOT)即取反
boolean a = true;
boolean b = false;
System.out.println("a&&b:"+(a&&b));//逻辑与运算,两个变量都为真(true),返回结果才为真(true)
System.out.println("a||b:"+(a||b));//逻辑或运算,两个变量中有一个为真(true),返回结果就为真(true)
System.out.println("!(a&&b):"+!(a&&b));//逻辑非运算,如果为真(true),则返回结果为假(false),
// 如果为假(false),则返回结果为真(true)
//短路运算
//在进行逻辑与运算时,若第一个变量为假(false),直接输出假(false),不再执行后面的代码。
//短路运算的一个实例:
int c = 5;
boolean d = (c<4)&&(++c>3);
System.out.println(d); //false,(c<4)为假,所以返回结果为假,直接跳过++c的操作,不进行++c的运算,所以c的值仍为5
System.out.println(c); //5
} -
位运算符: &, |, ^, ~, >>, <<, >>>
public static void main(String[] args) {
int a=60; //60的八位二进制原码是0011 1100(1前面的0都是符号位)
int b=13; //13的八位二进制原码是0000 1101(1前面的0都是符号位)
//--------------------------------------------------------------------------------------
System.out.println(a&b); //12 12的八位二进制原码是0000 1100 a&b的定义:参加运算的两个数据,按二进制位进行“与”运算。
//两个相应的二进制位中都为1,该位的结果值为1,有一个为0,则该位为0
//--------------------------------------------------------------------------------------
System.out.println(a|b); //61 61的八位二进制原码是0011 1101 a|b的定义:参加运算的两个数据,按二进制位进行“或”运算。
//两个相应的二进制位中都为0,该位的结果值为0,有一个为1,则该位为1
//--------------------------------------------------------------------------------------
System.out.println(a^b); //49 49的八位二进制原码是0011 0001 a^b的定义:参加运算的两个数据,按二进制位进行“异或”运算。
//参加运算的两个对象,如果两个相应位相同为0,相异为1。
//--------------------------------------------------------------------------------------
System.out.println(~b); //-14 -14的八位二进制原码为1000 1110,第一位为符号位"+"为0,"-"为1,其为1111 0010的原码
// (负数补码符号位不变,其余位取反,然后再+1,正数补码不变),计算机中数字都以补码的方式来储存,
// 尤其是当符号位为"1",则数字为负,要计算补码来确定数字,所以可发现 b:0000 1101通过“~”的运算变为 ~b:1111 0010,
// 可见~b符号位为1,为负数,则 1111 0010是一个负数的补码,通过逆运算的 1111 0010 - 1 = 1111 0001
//再取1111 0001反码得 1000 1110 即~b的二进制是1000 1110即-000 1110转为10进制为-14
//故 ~b的定义:参加运算的一个数据,按其补码的每一位进行“取反”运算。
// 即0→1,1→0
//--------------------------------------------------------------------------------------
//注意,这里所谓的按二进制是针对正数,负数算的是补码。
// (正数的补码与其二进制数一致,只需加上符号位”0“,而负数补码负数补码符号位“1”不变,其余位取反,然后再+1)
//--------------------------------------------------------------------------------------
System.out.println(-14>>3); // -2,-2的原码是1000 0010 补码是1111 1110
// -14的补码是1111 0010,可发现向右位移了三位,低位溢出
//则右位移">>"的定义:低位溢出,符号位不变,并用符号位补溢出的高位
System.out.println(b>>3); //1 b=13,八位二进制码是0000 1101,
// 右移三位,低位溢出,高位补上符号位(0),得0000 0001,即1
System.out.println(-14<<3);//-112 -112的八位二进制原码是1111 0000 则补码是1001 0000
//-14的原码是1000 1110 补码是1111 0010
//可发现-112的补码1001 0000由-14的补码1111 0010左移三位
// 则左位移(<<)的定义:符号位不变,低位补0。
//常见的算数位移的使用方法
System.out.println(2<<3); //16 2的原码是0000 0010 左移三位得0001 0000 转换为十进制为16,
// 可发现二进制数每左移1位,就相当于乘了一次2,所以2<<3 = 2*2^3
//同理有
System.out.println(9<<3); //72 即9<<3 = 9*2^3 = 72,计算机在处理这种位移计算,要远远快于普通的乘法计算
//同理,右移一位相当于除一次2
System.out.println(16>>3); //2 即16>>3 = 16/2^3 = 2
//注意,如果除不尽就按照这个数除以2的位移数的次方得到的整数结果,例如
System.out.println(23>>3); //2 23/2^3=23/8=2......7
} -
条件运算符:?(三元运算符)
写法为x ? y : z,例如:
public static void main(String[] args) {
int score = 50;
//x ? y : z 表示:
//若x==true ,则结果为y,否则结果为z
//属于if语句的简化写法,非常重要
String type = score<60?"不及格":"及格";
System.out.println(type); //不及格
} -
扩展赋值运算符:+=, -=, *=, /=
//扩展赋值运算符
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int e = 50;
a+=b; //a = a+b
c-=b; //c = c-b
d*=b; //d = d*b
e/=b; //e = e/b
System.out.println(a); //30
System.out.println(c); //10
System.out.println(d); //800
System.out.println(e); //2
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现