public class OperatorDemo{ public static void main(String[] args){ byte b = 127; b = b + 1;//会报错,因为b是变量不是字面量,java不能确定是否会超限 System.out.println(b); } }
字面量:literal
变量:variable
public class OperatorDemo{ public static void main(String[] args){ byte b = 127; b ++;//编译通过,结果为-128 System.out.println(b); } }
cmd命令: javap -c -v -s OperatorDemo
D:\dedu\day2>javap -c -v -s OperatorDemo Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 Classfile /D:/dedu/day2/OperatorDemo.class Last modified 2022年1月23日; size 410 bytes SHA-256 checksum 8a0b58bea984668b62c30fb415b7a4206363e6f52eb26a9ca386c0aaf62c2094 Compiled from "OperatorDemo.java" public class OperatorDemo minor version: 0 major version: 61 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #19 // OperatorDemo super_class: #2 // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 1 Constant pool: #1 = Methodref #2.#3 // java/lang/Object."<init>":()V #2 = Class #4 // java/lang/Object #3 = NameAndType #5:#6 // "<init>":()V #4 = Utf8 java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Fieldref #8.#9 // java/lang/System.out:Ljava/io/PrintStream; #8 = Class #10 // java/lang/System #9 = NameAndType #11:#12 // out:Ljava/io/PrintStream; #10 = Utf8 java/lang/System #11 = Utf8 out #12 = Utf8 Ljava/io/PrintStream; #13 = Methodref #14.#15 // java/io/PrintStream.println:(I)V #14 = Class #16 // java/io/PrintStream #15 = NameAndType #17:#18 // println:(I)V #16 = Utf8 java/io/PrintStream #17 = Utf8 println #18 = Utf8 (I)V #19 = Class #20 // OperatorDemo #20 = Utf8 OperatorDemo #21 = Utf8 Code #22 = Utf8 LineNumberTable #23 = Utf8 main #24 = Utf8 ([Ljava/lang/String;)V #25 = Utf8 SourceFile #26 = Utf8 OperatorDemo.java { public OperatorDemo(); descriptor: ()V flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]);//这里开始执行主函数 descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: bipush 127 //内存存储一个变量 2: istore_1 //都是int 3: iload_1 4: iconst_1 //常量化 5: iadd //add自增 6: i2b //int to byte 7: istore_1 8: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 11: iload_1 12: invokevirtual #13 // Method java/io/PrintStream.println:(I)V 15: return LineNumberTable: line 3: 0 line 4: 3 line 5: 8 line 6: 15 } SourceFile: "OperatorDemo.java"
底层有强制转换
任何数据在计算机中存储为补码。
原码,反码,补码
补码:规定最高位为符号位,如果为0则为整数,为1则为负数
byte b = 127; //byte占一个字节
127 = 0111 1111 ---- 二进制原码
byte b = -5; // byte 还占一个字节
-5 = 1000 0101 ---- 二进制原码
正数的原码,反码,补码规定一致
+127(正数)
0111 1111 — 原码
0111 1111 — 反码
0111 1111 — 补码
负数的反码:在原码的基础上,0变1,1变0;
负数的补码:在反码的基础上,加1
-5
1000 0101 — 原码
1111 1010 — 反码
1111 1011 — 补码
int i = -19
原码:10000000 00000000 00000000 00010011
反码:11111111 11111111 11111111 11101100
补码:11111111 11111111 11111111 11101101
byte ------- -128~127
byte b = -127
0:0000 0000 ------ 1000 0000
计算机中规定: 1000 0000 可以表示最小值 -128, -0 == -128
除=外,其余符号均要求已经初始化变量
= += -= *= /= %= &= |= ^= <<= >>= >>>=
byte b = 120; b += 55; System.out.println(b);//b的值为-81
120: 0111 1000 ---- 补码:00000000 00000000 00000000 01111000
55: 0011 1111 ---- 补码:00000000 00000000 00000000 00110111
120 + 55: ----------- 补码:00000000 00000000 00000000 10101111
补码:10101111
反码:10101110
原码:11010001 -------- -81
java中支持变量的连等运算?
public class OperatorDemo{ public static void main(String[] args){ int j; int i; i = j = 5; i += 3; System.out.println(i);//打印输出8 } }
public class OperatorDemo{ public static void main(String[] args){ //运算的时候是从左往右编译的 //在计算结果的时候从右往左计算 //i = 5 + ( 5 - (5/5)); int i = 5; i += i -= i /= 5; //9 i = 5; i -= i *= i; //-20 //i = 5 - (5 * 5); System.out println(i); } }
面试题:
i = i++; //5
注意赋值运算的脸等运算!
== 判断两个值是否相等
!= 判断两个值是否不相等,<><=>=
针对逻辑值进行运算的
与,或,非,异或,短路与,短路或
and,or,not,xor
& – 与运算,表示and,并且,
true & true = true
true & false = false
false & true = false
false & false = false
| – 或运算,表示or,或者
true | true = true
true | false = true
false | true = true
false | false = false
!-- 非运算,表示not,取反
! true = false
! false = true
^ – 异或,x表示xor
相同则为假,不同则为真(eg:电磁学:同极相斥,异极相吸)
ture ^ true = false
false ^ true = true
true ^ false = true
false ^ false = false
&& – 短路与,和与运算的结果是一致的,如果前面的结果是false,后面的表达式就不计算了(有短路特性,效率提升)
|| – 短路或,和||的运算规则相一致,如果前面的结果是true,后面的表达式就不计算了(有短路特性,效率提升)
eg:
public class OperatorDemo{ public static void main(String[] args){ int i = 3, j = 6; boolean b = i < 2 & j++ > 3;//因为i=3所以b的值一定是false, System.out.println(b);//false System.out.println(j);//7 } }
public class OperatorDemo{ public static void main(String[] args){ int i = 3, j = 6; boolean b = i < 2 && j++ > 3;//因为i=3所以b的值一定是false,后续不再计算 System.out.println(b);//false System.out.println(j);//6 } }
&&在||前不能短路||
||在&&前可以短路&&
只能算整数,不能算其他
&–与 |–或 ^–异或 <<–左移 >>–右移 >>>–无符号右移 ~–取反
&运算
5&8=0
数据转化为补码,按位与计算:
00000101 – 5
00001000 – 8
00000000 – 0
9&11=0
数据转化为补码,按位与计算:
00001001 – 9
00001011 – 11
00001001 – 9
正数&负数:结果一定是整数
偶数&其他数:结果一定是偶数
0&任何数 = 0
1&奇数 = 奇数
1&偶数 = 0
|运算
5&8=13
数据转化为补码,按位或计算:
00000101 – 5
00001000 – 8
00001101 – 13
9|11=11
数据转化为补码,按位与计算:
00001001 – 9
00001011 – 11
00001011 – 11
负数|任何数:结果一定是负数
奇数|任何数:结果一定是奇数
0 & 任何数:结果是原数
^运算> 5&8=13
数据转化为补码,按位或计算:
00000101 – 5
00001000 – 8
00001101 – 13
9|11=0
数据转化为补码,按位与计算:
00001001 – 9
00001011 – 11
00000010 – 2
任何数 ^ 任何数:结果是0
0 ^ 任何数:结果是原数
a ^ b ^ b = a
1. 用异或运算交换值
int x = 5, y = 7; x = x ^ y; y = x ^ y; x = x ^ y; //x = 7, y = 5;
2.加减法交换值
int x = 3, y = 7; x = x + y; y = x - y; x = x - y;
3.第三方变量交换值
int x = 3, y = 7; int temp = x; x = y; y = temp;
三种方式优劣性:
位运算符:
左移:
3<<2 (向左移动两位)
将数据转化为补码之后按指定的位数移动,溢出的数据舍弃,低位次空出补0,最后转化为十进制
6<<3
6 – 00000110 – 00110000 – 80
左移可能会出现正变负或负变正的情况
在一定范围内,左移几位就是乘以2的几次方
右移:
9>>2(向右移动两位)
00001001
讲数据转化为补码之后按指定位数移动,溢出的数据舍弃,正数补0负数补1
00000010
正数右移,越移越小,最小到0
负数右移,越移越大,最大到-1
在一定范围内,右移几位就是除以2的几次方
无符号右移
将数据转化为补码之后,按照指定的位数向右移动,溢出的数据舍弃,高位次空出,无论正负一律补0,最后结果转化为十进制显示
在进行移位运算的时候,并不是直接移动对应的位数,而是将移动的位对32进行取余,移动的是余数对应的位数
28<<35 = 28<< (35%32) = 28<<3
100 << 32 = 100
取反
快速计算规律:
取负数再减一
~3 = -4
~(-13) = 12
~25 = -26
~3 补码:00000011
转化为补码一律取反:11111100
反码:11111011
原码:10000100
-4
~3 = -4
~(-13) = 12
原码:10001101
反码:11110010
补码:11110011
取反:00001100
补码=反码=原码= 00001100 = 12
~25 =
原码:00011001=反码=补码
取反:11100110
反码:11100101
原码:10011010 = -26
算数,赋值,关系,逻辑,位
赋值优先级最低!
算数运算符 高于 关系运算符
算术运算符 高于 位运算符
关系运算符 高于 位运算符
算数:+ - * / ++ – %
赋值:=
关系:== != > < >= <=
逻辑:& | ! ^ && ||
位:& | ! << >> >>>
public class OperatorTest{ public static void main(String[] args){ System.out.println(3>2+3);//输出false,说明先机算了2+3,因此输出false System.out.println(true && 2>3);//并未报错,说明先机算了2>3然后计算&& System.out.println(true && 2);//会报错! System.out.println(3 + 5 & 1);//输出0,8&1=0,说明先算了算术运算符 System.out.println(3 > 5 & 1);//报错,说明先算了关系运算符 System.out.println(3 + 2 << 2);//输出20,说明先计算了3+2,5<<2 = 20 System.out.println(3 > 2 << 2);//输出false System.out.println(~2 * 5);//8 } }
逻辑值 ? 表达式1 : 表达式2
逻辑值为true,则执行表达式1
逻辑值为false,则执行表达式2
三元摆到时依然是一个表达式,所以需要有一个计算结果,这个计算结果可以被一个变量存储
double d = a > b ? 3.5 : 5 //可以定义一个double类型
a > b ? 3 : true; // 报错,因为结果类型不兼容
double d = a > b ? ‘a’ : 2.26; // char可以自动提升为int,int可以提高为double
()
一元运算:~ ++ – !
二元运算:* / % + - << >> >>> 关系 逻辑 & | ^
三元
赋值
整数n,快速判断n是否是2^x的形式
n & (n-1) == 0
System.out.println(5 * 16);//效率低 //计算过程,先将5和16都转化成最开始的补码,然后开始按位运算 System.out.println(5 << 4);//效率更高
流程控制:
顺序结构:代码从上到下,从左到右依次编译执行
分支结构:判断结构/选择结构
循环结构:
从控制台获取数据:
import java.util.Scanner; //表示到java.util包下找scanner public class OperatorTest{ public static void main(String[] args){ scanner s = new Scanner(System.in); //只有如下三种写法 int i = s.nextInt(); double d = s.nextDouble(); String str = s.nextLine(); } }