【Java】操作符

算数操作符

取余/取模
+-*/%

这里稍微讲解几个注意点:

  1. 除法和取余的时候,被除数不能为0
  2. 取余可以用小数,但是没什么用~~(你都要小数你还不如直接浮点数除法得了)~~

这里关于取余的负数运算可能有人有点晕,这里稍微讲解一下

public class Test {
    public static void main(String[] args) {
        System.out.println(10 % 3);
        System.out.println(10 % (-3));
        System.out.println((-10) % 3);
        System.out.println((-10)%(-3));
        //输出结果为 1 1 -1 -1
    }
}

取余运算,如果写成小学我们经常写的余数运算格式就是:a / b = c......d,我们取余拿的就是d

那么d是怎么来的呢,实际上就是d = a - (b * c)

分别解释一下这上面个运算:

  • 第一个非常简单,相当于10 / 3 = 3......1
  • 第二个稍微可能有人看不懂,但是我相信写出小学写的那个算数式子没人看不懂,相当于10 / (-3) = (-3)......1
  • 第三个,看不懂就写算术式子,相当于(-10) / 3 = (-3)......-1
  • 第四个,相当于(-10) / (-3) = 3......-1

移位操作符

上一节我们有谈到过数据的存储,我们得知整型数据在内存中存储的是补码,所以涉及到二进制位的操作符都是操作补码

左移右移
<<>>

注意:该类操作符只能操作整数

左移操作符

左移,即全部数字向左移动一位,空位补0,移到外面的直接舍去

public class Test {
    public static void main(String[] args) {
        int a = 3;
        //原反补 00000000000000000000000000000011
        int b = -3;
        //原  10000000000000000000000000000011
        //反  11111111111111111111111111111100
        //补  11111111111111111111111111111101
        System.out.println(a << 1);
        //移后补码 00000000000000000000000000000110
        //移后原码 00000000000000000000000000000110
        //输出6
        System.out.println(b << 1);
        //移后补码 11111111111111111111111111111010
        //移后原码 10000000000000000000000000000110
        //输出-6
    }
}

多试几个数就会发现,左移n位就是乘以2的n次方

右移操作符

右移操作符在Java中补的是符号位

public class Test {
    public static void main(String[] args) {
        int a = 8;
        //原反补 00000000000000000000000000001000
        int b = -3;
        //原 10000000000000000000000000000011
        //反 11111111111111111111111111111100
        //补 11111111111111111111111111111101
        int c = 9;
        //原反补 00000000000000000000000000001001
        
        System.out.println(a >> 1);
        //移后原反补 00000000000000000000000000000100
        //输出4
        System.out.println(b >> 1);
        //移后原 11111111111111111111111111111110
        //移后反 10000000000000000000000000000001
        //移后补 10000000000000000000000000000010
        //输出-2
        System.out.println(c >> 1);
        //移后原反补 00000000000000000000000000000100
        //输出4
    }
}

就相当于整型的除以2的n次方

无符号右移操作符

补位不再补符号位,而是直接补0

public class Test {
    public static void main(String[] args) {
        int a = 0xffffffff;
        //这里是赋予一个16进制数字
        //0x带头就是指后面的是一个16进制数 
        System.out.printf("%x\n", a >>> 1);
        //这里输出格式是以16进制打印
        //打印出的结果是 0x7ffffff
    }
}

这里就顺便提一下16进制和2进制的关系,2进制的4个位相当于16进制的1个位

16进制的表示是
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
0 1 2 3 4 5 6 7 8 9  a  b  c  d  e  f 

0xffffffff
实际上就相当于二进制的
1111 1111 1111 1111 1111 1111 1111 1111
 15   15   15   15   15   15   15   15  
    
上面的代码向无符号右移位一位,实际上就是
0111 1111 1111 1111 1111 1111 1111 1111
  7   15   15   15   15   15   15   15 
所以16进制就是0x7ffffff

位操作符

按位取反异或
&|~^

关于&|,就将二进制中的0和1作为是和否去判断

0000000111			 0011001100
&		 	 		|	
0001100011			 0011000000
=		  			=
0000000011			 0011001100

~,顾名思义就是取反,没什么可以多说的

~00000001 = 11111110

^,二进制相同就取1,不同就取0

0011110000
^
0000110011
=
1100111100

那么根据异或的定义,我们可以得出两个重要性质

a ^ a = 0
a ^ 0 = a
//甚至可以拓展为
a ^ b ^ a= b;
//异或支持交换律,所以上面的拓展实际上就等于
a ^ a ^ b = b

用异或还可以写一个很奇怪的变量数据交换代码,可以不创建临时变量交换数值

public class Test {
    public static void main(String[] args) {
        int a = 3;
        int b = 5;
        System.out.println("交换前:a = " + a + " b = " + b);
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        System.out.println("交换后:a = " + a + " b = " + b);
    }
}

举一个例子来帮助理解上面的代码,假设a = 3 b = 5

a = 3 ^ 5;
b = 3 ^ 5 ^ 5;//这个时候b = 3;
a = 3 ^ 5 ^ 3;//这个时候a = 5

当然平常不推荐这样写,只不过之前有类似不让创建临时变量而要求交换数据的题目,所以这里提及一下

增量操作符

+=-=*=/=%=
>>=<<=&=|=^=

举例说明一下实际意义

public class Test {
    public static void main(String[] args) {
        int a = 0;
        a += 3;
        //上面和下面效果是一样的
        a = a + 3;
    }
}

其他的都是类型的就不多说了

自增自减运算符

++
自增自减

举一个例子来帮忙解释

public class Test {
    public static void main(String[] args) {
        int a = 0;
        a++;
        System.out.println(a);
        //实际上就等于a = a + 1;
    }
}

但是这两个符号,写在变量名前面和后面的含义不同

public class Test {
    public static void main(String[] args) {
        int a = 0;
        int b = 0;
        System.out.println(a++);
        System.out.println(a);
        System.out.println(++b);
        System.out.println(b);
        //输出的为 0 1 1 1
    }
}

自增写在前面,就是先++后使用,写在后面就是先使用后++

自减和自增是同理的,所以不再多说

关系操作符

>>=<<=!===
大于大于等于小于小于等于不等于等于

关系操作符计算的结果是boolean类型

注意,如果限定条件比较多,比如要3 < x < 5

千万不能和上面一样直接写,只能一个一个的判断,并且结合下面的逻辑操作符把他们连起来

public class Test {
    public static void main(String[] args) {
        int a = 0;
        //如何写 3 < a < 5,没看懂就看下面的逻辑操作符
        System.out.println(a > 3 && a < 5);
    }
}

逻辑操作符

&&||!
逻辑与逻辑或逻辑非

就是正常的逻辑逻辑判断符,逻辑运算符只能运算boolean类型

  • 与,有假则假,全真则真
  • 或,有真则真,全假则假
  • 非,假真互换
public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 1;
        System.out.println(a == 1 && b == 1);//true
        System.out.println(a == 1 && b == 0);//false
        System.out.println(a == 0 || b == 0);//false
        System.out.println(a == 1 || b == 0);//true
        System.out.println(!(a == 0));//true
        System.out.println(!(a == 1));//false
    }
}

阅读完上面的代码,实际上对于逻辑运算符基本就掌握的差不多了,但是还有一些注意点值得一提

当从左向右依次判断时,&&判断中若出现一个假直接判断为假,后方不在计算。同理,||判断中若出现一个真直接判断为真,后方不在计算,这个被称作短路运算

public class Test {
    public static void main(String[] args) {
        int a = 1;
        //a为0直接为假,后方不再计算, 所以本来理论上会报错的代码没有报错
        System.out.println(a == 0 && 10 / 0 == 0);
        int b = 1;
        //b为1直接为真,后方不再计算,所以本来理论上会报错的代码没有报错
        System.out.println(b == 1 || 10 / 0 == 0);
    }
}

上面我们提到的位操作符& |,实际上在它们识别到附近为boolean类型的时候,就会变为逻辑操作符,但是它们不会进行短路运算

public class Test {
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a == 0 & 10 / 0 == 0);
        int b = 1;
        System.out.println(b == 1 | 10 / 0 == 0);
        //都会报错
    }
}

条件操作符

exp1 ? exp2 : exp3

如果exp1true,则表达式的值为exp2,否则表达式的值为exp3

public class Test {
    public static void main(String[] args) {
        int a = 0;
        int b = 0;
        b = (a > 5) ? 5 : 3;
        System.out.println(b);
        //输出3
    }
}

操作符优先级

操作符是有优先级的,如果表达式比较复杂,那么表达式可能就不会按照我们预想的方式进行运算

但是操作符的优先级多而杂,不推荐记忆,推荐在表达式中适当的加上括号保证运算符合我们的要求即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值