4.逻辑运算符
/*
逻辑运算符(运算符中相当重要的一个符号)
应用场景:在实际开发中,对业务层代码中需要对相关的业务需求进行
逻辑判断
比如:用户要注册/用户要登录
注册---需要在数据库中找是否存在这个用户
登录:用户名和密码必须一致,如果不一致,不能登录;
基本的逻辑运算符
逻辑单与& (并列关系)
特点:有false,则false
逻辑单或| (或的关系)
特点: 有true,则true
逻辑异或^
特点: 相同则为false,不同则为true
简单记忆:
男女关系问题
男男 :false
女女 :false
男女 : true
女男 : true
逻辑非!
特点:非true,则false;非false,则true
偶数个非是它本身!
*/
class OperatorDemo{
public static void main(String[] args){
//定义三个变量
int a = 3 ;
int b = 4 ;
int c = 5 ;
//逻辑单与& (并列关系),条件必须同时满足才成立
System.out.println((a>b) & (a>c)) ;//false & false =false
System.out.println((a>b) & (a<c)) ;//false & true =false
System.out.println((a<b) & (a>c)) ;//true & false =false
System.out.println((a<b) & (a<c)) ;//true & true = true
System.out.println("---------------------------------------------") ;
//逻辑单或| (或的关系):满足一个条件即可成立
System.out.println((a>b) | (a>c)) ; // false | false =false
System.out.println((a>b) | (a<c)) ; //false | true = true
System.out.println((a<b) | (a>c)) ;//true | false = true
System.out.println((a<b) | (a<c)) ;//true | true =true
System.out.println("---------------------------------------------") ;
//逻辑异或^ (或的关系)
System.out.println((a>b) ^ (a>c)) ; // false ^ false = false
System.out.println((a>b) ^ (a<c)) ; //false ^ true = true
System.out.println((a<b) ^ (a>c)) ;//true ^ false = true
System.out.println((a<b) ^ (a<c)) ;//true ^ true = false
System.out.println("---------------------------------------------") ;
//逻辑非!
System.out.println(!(a>b)) ;
System.out.println(!!(a>b)) ;
System.out.println(!!!(a<c)) ;
}
}
/*
重点:逻辑双与&&特点
面试题
逻辑双与&&和逻辑单与&有什么区别?
共同点:
都是表示并列关系,基本特点:有false,则false
不同点:
具有"短路"效果
逻辑双与&& 连接的表达式:如果左边是一个false,右边就不执行了!逻辑双或||和逻辑单|的区别
基本的特点:有true,则true,表示或的关系
不同点:
逻辑双或||连接的左边表达式如果是true,右边不执行了,具有短路效果!
好处:提高逻辑判断的执行效率,开发中经常使用时逻辑双与&&和逻辑双或||举例
if(xx && xx && xx)----->节省局部变量在(栈内存)内存中内存空间,提高执行效率!
*/
class OperatorDemo2{
public static void main(String[] args){
//定义三个变量
int a = 3 ;
int b = 4 ;
int c = 5 ;
//逻辑双与&& 它基本的特点就和逻辑单与&相同的
System.out.println((a>b) && (a>c)) ; //false && false = false
System.out.println((a>b) && (a<c)) ; //false && true = false
System.out.println((a<b) && (a>c)) ; //true && false = false
System.out.println((a<b) && (a<c)) ;// true && true = true
System.out.println("-----------------------------------------") ;
//定义两个变量
int x = 3 ;
int y = 4 ;
System.out.println("x:"+x+",y:"+y) ;
System.out.println("===========================================") ;
//逻辑单与&
//System.out.println(((++x)==3) & ((y--)==4 )) ;//false
//System.out.println("x:"+x+",y:"+y) ;//4,3
//逻辑双与&& false
System.out.println(((++x)==3) && ((y--)==4 )) ;//false
System.out.println("x:"+x+",y:"+y) ;//"x:4,y:4"
}
}
5.位运算符
Java定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。
位运算符作用在所有的位上,并且按位运算。
假设a = 60,b = 13;它们的二进制格式表示将如下:
A = 0011 1100 B = 0000 1101 ----------------- A & B = 0000 1100 A | B = 0011 1101 A ^ B = 0011 0001 ~A= 1100 0011
下表列出了位运算符的基本运算,假设整数变量 A 的值为 60 和变量 B 的值为 13:
操作符 | 描述 | 例子 |
---|---|---|
& | 如果相对应位都是1,则结果为1,否则为0 | (A&B),得到12,即0000 1100 |
| | 如果相对应位都是 0,则结果为 0,否则为 1 | (A | B)得到61,即 0011 1101 |
^ | 如果相对应位值相同,则结果为0,否则为1 | (A ^ B)得到49,即 0011 0001 |
〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 | (〜A)得到-61,即1100 0011 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 | A << 2得到240,即 1111 0000 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | A >> 2得到15即 1111 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 | A>>>2得到15即0000 1111 |
/*
位运算符: 就是对当前这些数据进行计算的(补码进行计算的)
基本位运算符:
位与&: 有0则0
位或|: 有1,则1
位异或^: 相同则为0,不同则为1
有另一个特点(面试题考点)
一个数据被另一个数据如果位异或两次,其值是它本身!
~反码: 全部按位取反(0变1,1变0)
其他的位运算符:移位符号
<<:左移
>>:右移
>>>:无符号右移
*/class OperatorDemo{
public static void main(String[] args){
//位与&
System.out.println(3 & 4) ;
//位或|
System.out.println(3 | 4) ;
//位异或^
System.out.println(3 ^ 4) ;
//反码~
System.out.println(~3) ;
/*
0
7
7
-4
*/
}
}
/*
位与&:有0,则0
3 & 4 ---计算出3和4对应的二进制数据(原码---反码----补码) ,使用补码进行计算
00000000 00000000 00000000 00000011 --原码/反码/补码相同
00000000 00000000 00000000 00000100 --原码/反码/补码相同
-------------------------------------------------------------------
00000000 00000000 00000000 00000000
结果:0
位或|: 有1,则1
3 | 4
00000000 00000000 00000000 00000011 --原码/反码/补码相同
00000000 00000000 00000000 00000100 --原码/反码/补码相同
-------------------------------------------
00000000 00000000 00000000 00000111 --补码---反码---原码:相同
结果:7
位异或^:相同则为0,不同则为1
00000000 00000000 00000000 00000011 --原码/反码/补码相同
00000000 00000000 00000000 00000100 --原码/反码/补码相同
------------------------------------------------------------
00000000 00000000 00000000 00000111 --补码---反码---原码:相同
结果:7
反码~:此时将这个数据全部按位取反:0变1,1变0(不分最高符号位)
~3
3的原码----反码-补码相同
00000000 00000000 00000000 00000011 :
补码:进行 ~(反码操作)
~:反码:全部按位取反
00000000 00000000 00000000 00000011
11111111 11111111 11111111 11111100 ---补码----反码----原码
最高符符号位 数值位
1 1111111 11111111 11111111 11111100 补码
- 1
---------------------------------------------------
1 1111111 11111111 11111111 11111011 反码 (--原码:符号位不变,数值位按位取反)
1 0000000 00000000 00000000 00000100
- 4
*/
/*
编程题:
面试官其实际就是想问对位运算符的位异或的特点:
实现两个变量的数据进行交互
举例
int a = 10 ;
int b = 20 ;
最终要将a和b进行互换
*/
class OperatorTest{
public static void main(String[] args){
//有两个变量
int a = 10 ;
int b = 20 ;
System.out.println("a:"+a) ;
System.out.println("b:"+b) ;
System.out.println("---------------------------------------") ;
//方式1:使用中间第三方变量(最常用的一种方式:推荐使用第一种)
//定义临时变量temp
//记录a的值
int temp = a ; //int temp = a = 10
//在将b的值赋值给a //
a = b ;//a = 20
//将temp的赋值给b
b = temp ; //10
System.out.println("a:"+a) ;
System.out.println("b:"+b) ;
//方式2:使用位异或的特点^:一个数据被另一个数据位异或两次,其值是它本身
//左边:a,b,a
//右边都是: a^b
/*
a = a ^ b ; //a赋值 = a ^ b ;
b = a ^ b ; //b = a ^ b ^ b ; //b = a : 将a已经赋值给b了
a = a ^ b ; //a = a ^ b ^ a = b :将b的值赋值给a
System.out.println("a:"+a) ;
System.out.println("b:"+b) ;
*/
/*
a:10
b:20
---------------------------------------
a:20
b:10
*/
}
}
class Test {
public static void main(String[] args) {
int a = 60; /* 60 = 0011 1100 */
int b = 13; /* 13 = 0000 1101 */
int c = 0;
c = a & b; /* 12 = 0000 1100 */
System.out.println("a & b = " + c );
c = a | b; /* 61 = 0011 1101 */
System.out.println("a | b = " + c );
c = a ^ b; /* 49 = 0011 0001 */
System.out.println("a ^ b = " + c );
c = ~a; /*-61 = 1100 0011 */
System.out.println("~a = " + c );
c = a << 2; /* 240 = 1111 0000 */
System.out.println("a << 2 = " + c );
c = a >> 2; /* 15 = 1111 */
System.out.println("a >> 2 = " + c );
c = a >>> 2; /* 15 = 0000 1111 */
System.out.println("a >>> 2 = " + c );
}
}
以上实例编译运行结果如下:a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2 = 15
a >>> 2 = 15
/*
其他的位运算符:移位符号
<<:左移
将这个数据(补码)向左移动,将高位丢弃掉,右边补0
快速应用:
将<<这个符号左边的数据乘以2的移动次幂
面试题:
请用有效的方式快速写出 2乘以8的结果: 16
2 << 3 2左移3位
>>:右移
将这个数据(补码)向右移动,最高位是1,左边补1;最高位是0,左边补0;
快速使用:
将>>符号左边的数据除以2的移动次幂
>>>:无符号右移
无论最高位是1还是0,那么在左边始终补0
*/class OperatorDemo{
public static void main(String[] args){
System.out.println(3 << 2) ; //将3左移两位 //3 * 2的2次方 =12
System.out.println(24 >> 2) ; //6 // =24/2的2次方法 24/4 = 6
System.out.println(-24 >> 2) ;
System.out.println(-24 >>> 2) ; //-24无符号右移2位
}
}
/*
3<<2
将3对应二进制(原码)
00000000 00000000 00000000 00000011 原/反/补码一致
00000000 00000000 00000000 00000011 << 2
(00)000000 00000000 00000000 0000001100 补码---反码---原码
结果为12:
24 >> 2
二进制(原码)
00000000 00000000 00000000 00011000 (原码,反码,补码)
0000000000 00000000 00000000 000110(00) 补码 ---反码---补码
0000000000 00000000 00000000 000110
结果为6
-24 >> 2
1 0000000 00000000 00000000 00011000 原码
1 1111111 11111111 11111111 11100111 反码
+ 1
-------------------------------------
1 1111111 11111111 11111111 11101000 补码 >> 2
111 1111111 11111111 11111111 111010(00)
11 11111111 11111111 11111111 111010 补码移动的结果
最高符号位 数值位
1 1 11111111 11111111 11111111 111010 补码
- 1
-----------------------------------------------
1 1 11111111 11111111 11111111 111001 反码
1 0 00000000 00000000 00000000 000110 原码
- 6
-6
-24 >>> 2
1 0000000 00000000 00000000 00011000 原码
1 1111111 11111111 11111111 11100111 反码
+ 1
-------------------------------------
1 1111111 11111111 11111111 11101000 补码 >>> 2 (无符号右移)
00 1 1111111 11111111 11111111 111010(00)
00 1 1111111 11111111 11111111 111010 :补码---反码---原码
结果:1,073,741,818
*/
6.三元运算符
/*
三元运算符---(三目运算符)
二目运算符 int m =20,n =10;
单目运算符 int a = 10 ;
三元运算符的格式
(表达式)?执行 true的结果:执行false 的结果;
表达式:可以简单可以非常复杂
流程:
首先判断表达式是否成立,如果成立,则执行true的结果
否则,执行false的结果;
举例:
有两个变量 ,需要比较两个数据中的最大值;
讲课中,没有明确数据类型,都默认int*/
class OperatorDemo{
public static void main(String[] args){
//定义两个变量
int a = 10 ;
int b = 20 ;
//比较较两个数据中的最大值
//(表达式)?执行 true的结果:执行false 的结果;
//定义最终结果变量
int max = (a>b)?a:b;
System.out.println(max) ; //20
System.out.println("------------------------------------") ;
//a和b中的最小值
int min = (a<b)?a:b ;
System.out.println("a和b的最小值是:"+min) ;
System.out.println("------------------------------------") ;
//比较三个数据中的最大值
int x = 20 ;
int y = 40 ;
int z = 10 ;
//方式1:使用中间变量的方式 (推荐的,步骤清晰明了)
//定义temp,记录x和y的最大值
int temp = (x>y)?x:y ;
//然后使用temp和z进行三元运算符
//定义接收结果变量max2
int max2 =(temp >z)? temp : z ;
System.out.println("三个数据中的最大值是:"+max2) ;
System.out.println("---------------------------------------") ;
//方式2:三元运算符是可以嵌套的 (一步走)
//定义最终变量max3
int max3 = (x >y)?((x>z)?x:z):((y>z)?y:z) ; //推荐第一种方式
//int max3 = x >y?x>z?x:z:y>z?y:z ;
System.out.println("三个数据中的最大值是:"+max3) ;
}
}
键盘录入数据
/*
在写程序的过程中,想让程序更加灵活,使用Scanner类:
jdk提供的这个类----作用 "一个简单的文本扫描器"
目前:就是录入int类型数据
操作步骤
1)导包 import(关键字) java.util.Scanner ; 格式必须class类上面
需要在我当前的代码中使用jdk提供的这个类Scanner
2)创建一个文本扫描器对象 (键盘录入对象)
固定格式
Scanner 对象名(自己起名字) = new Scanner(System.in) ;
3)友情提示并录入int类型数据
System.out.println("请您输入一个数据:") ;
表示:录入的是int类型数据
int 接收的变量名 = 对象名.nextInt() ; //nextInt() ;键盘录入Scanenr的方法
4)然后 "接收的变量名 "输出出来"
*/
//导包1)
import java.util.Scanner ;class ScannerDemo{
public static void main(String[] args){
//2)创建一个文本扫描器对象 (键盘录入对象)
//固定格式
//Scanner 对象名(自己起名字) = new Scanner(System.in) ;
Scanner sc = new Scanner(System.in) ;
//3)友情提示并录入int类型数据
System.out.println("请您输入一个数据(int):") ;
//int 接收的变量名 = 对象名.nextInt() ;
int a = sc.nextInt() ;
//4)输出下a,看效果
System.out.println("a的值是:"+a) ;
}
}
/*
没有提示数据类型,都是int
/比较较两个数据中的最大值,然后优化---使用键盘录入两个数据
*/
//导包
import java.util.Scanner ;
//在Java中只要这些类不是java.lang包下的都需要import
class Test1{
public static void main(String[] args){
//创建文本扫描器对象(键盘录入对象)
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请您输入第一个数据:") ;
//录入
int firstNum = sc.nextInt() ;
System.out.println("请您输入第二个数据:") ;
//录入
int secondNum = sc.nextInt() ;
//比较较两个数据中的最大值,
//三元运算符
int max = (firstNum>secondNum) ? firstNum : secondNum ;
System.out.println("两个数据中的最大值是:"+max) ;
}
}