基本数据类型取值范围从小到大
1.byte<short<int<long<float<double
面试题:long占8个字节,float占4个字节,为什么float的取值范围大于long类型的取值范围
1.基本类型的类型转换只和取值范围有关,和占用字节数无关。
2.long类型底层是十进制整数,float类型底层是一套 IEEE二进制浮点数算术标准(IEEE 754),不是十进制整数。
float通过精度损失加大取值范围
3.手动数学证明:long类型最大整数<2^63 (-2的63次方到2的63次方-1)
float类型最大整数(如下截图)
在这块我就有个疑惑是这样的:各位看看????
我他吗就是理解不了,尤其是红字体。0111 1111(正数)要获取原码应该是他本身吧。打10万个问号???????
最小的负数就是1000 0000,(最大的负数是 1111 1111 是负数-1的补码),换算成十进制就是 -128, 1000 0000 是最小负数的补码表示形式,我们把补码计算步骤倒过来就即可。1000 0000 减 1 得 0111 1111 然后取反 1000 0000 因为负数的补码是其绝对值取反,即 1000 0000 为最小负数的绝对值,而 1000 0000 的十进制表示是 128,所以最小负数是 -128
2.char<int<long<float<double
char ->int(可以) int->char(不行) //int可能取-1char->short(不行) short->char(不行)//因为char可能取60000,short可能取-1
3.boolean类型不支持基本数据类型转换
基本类型与基本类型之间的转换----自动类型转换
(隐式转换,小范围自动转大范围,隐式转换可用可不用转换格式)
int num01=123;long num02=(long)num01;//int转long,可用但不推荐使用()long num_02=num01;//隐式转换int转long 推荐不加()System.out.println(num02);//123System.out.println(num_02);//123
强制转换 必须使用类型转换格式
强制转换是取值范围大的转取值范围小的
int num=(int)3.99;//num=3,double转int,只要整数部分
强制类型转换可能会发生数据溢出和数据损失
数据溢出:byte num=(byte)130;//num=-126,通过“原反补”计算得出//类似时钟,130=127+3(-128,-127,-126)
秀一波操作,
负整数从补码转反码:反码=补码-1
负整数从反码转原码:对反码逐位进行取反(除去符号位)
00000000 00000000 00000000 1000 0010(130补码)强转byte(1字节),结果补码变为1000 0010再转回原码 :1000 0010(补码)---1000 0001(反码)--1111 1110(原码,转为十进制就是-126)
特殊注意
*在程序中,byte、short、char发生数学运算会越级提升为int再参与运算。
byte b1=3;byte b2=4;byte res=b1+b2;//会报错,b1、b2先提升为int
编译器常量优化机制:
在Java语言当中,byte,short,char,这三种数据类型在初始化赋值的时候是整数字面值常量,
且没有超出其数据类型的取值范围。jvm中的常量区在编译时期将初始化值优化为对应数据类型
byte num=123;//123是int
给变量初始化赋值的时候,如果初始化值是一个计算式子。运算符号俩边都是字面值常量,且运算结果在变量数据类型的取值范围内,jvm常量区会在编译时期自动运算完毕。
byte sum=3+4;//运行时就为byte sum=7char ch='J';char c='J'+32;System.out.println(c);//j
常量:在程序中其值不可以发生改变的量
常量分为字面值常量 、自定义常量(final)。
字面值常量:整数字面值、小数字面值(参与数学运算才会精度损失)、
布尔字面值、字符字面值、字符串字面值、空字面值null
注意:
空字面值不可以直接打印,可以间接打印。System.out.println(null);//报错
输出语句
换行输出:System.out.println("HelloWorld");直接输出:System.out.print("HelloWorld");//去掉ln
换行输出在没有输出内容:System.out.println(),会进行回车换行
直接输出语句没有输出内容时:System.out.print();会编译报错
算术运算符
计算运算符 + - * / %(取余不是取模)
/和%区别:
/:计算相除的商,只拿商%:计算俩个数相除的余数,只拿余数
+:字符串连接符
当+俩边任意一边是字符串,+就变为字符串连接符
System.out.println('a'+1);//98System.out.println(""+'a'+1);//a1
自增++:一个运算符,俩个动作。格式直接使用(变量++,++变量)
单独使用:
单独使用的时候,变量++,++变量结果是一样的。a++;++a;
复合使用:
int x=3;int y=++x; //y=4 ++在前,先加再使用
int x=3;int y=x++; //y=3 ++在后,先使用变量再自增
自己编的测试程序:【自豪】
使用指的是给=左边的值赋值吧,,22-08-05回看
/** ++在前,先加再使用++在后,先使用再自增*/int a=3;int b=++a + a++;//b=4+4 a=5int b0=a++ + ++a;//b0=5+7 a=7int b1=a++ + a++;//b1=7+8 a=9int b2=++a + ++a;//b2=10+11 a=11System.out.println(a);System.out.println("结果:"+b+"-"+b0+"-"+b1+"-"+b2); //8-12-15-21
思考题:
i=++i;先加加再赋值,打印的就是加过的值
public class Demo {public static void main(String[] args) {int i=0;i=++i;System.out.println(i);//1}}
要是这样呢 i=i++
先赋值后加加,则在下面打印的时候时打印赋值后的,在后面的运算里i再加1
public class Demo {public static void main(String[] args) {int i = 0;i = i++;System.out.println(i);//0}}
自减 --
--:一个运算符,俩个动作。变量-1运算以后再将结果赋值给该变量。
经典练习:获取数字的每一位上的数字 【经典永不过时】
先取商再取余
int num=1234;int ge=num%10;//获取个位数字4int shi=num/10%10;//获取十位数字3int bai=num/100%10;int qian=num/1000%10;
赋值运算符
=、+= 基本使用
int num=3;//将整数3赋值给int类型变量numint a=3,b=4;a+=b;//相当于a=a+b
扩展赋值运算符运算完毕以后,赋值时根据左边运算符进行强制类型转换
byte b1=3;byte b2=4;b1=b1+b2;//报错b1+=b2;//编译通过
扩展赋值运算符会将“=”左边的变量和右边表达式的结果进行运算操作
int a=3;int b=4;a*=b+5; //a *(b+5)=27
关系运算符
【<,<=,>,>=,==,!=】关系表达式的结果一定是布尔值
逻辑运算符
连接多个判断条件的运算符
标准逻辑运算符&,|,^, !
&:有false则false。 |:有true则true ^:异或。俩边相同为false,俩边不同为true !: !!true(负负得正,2个!一划掉)
短路逻辑运算符&&,|| 这里我就不得不提了,java里没有and,or。。
&&和&的结果是一样的。&&具有短路效果(实际应用推荐&&) ||和|的结果是一样的。||具有短路效果(实际应用推荐||)
经典练习:判断闰年
闰年的判断标准是: 可以被4整除,但不可被100整除 可以被400整除
int year = ; boolean result = year%4==0 && year%100!=0 || year%400==0; System.out.println(year + (result ? "是闰年" : "不是闰年"));
三元运算符
含有三个未知量的运算符
关系表达式 ?结果值1:结果值2
流程:关系表达式是true,执行类型转后的结果1;如果是false,执行类型转换后的结果2
基本使用
int a=3,b=4;
sout(a>b ?a : b)//4
坑爹操作:
System.out.println(true ? 3 : 4.5);//3.0
执行结果3.0,三元运算符将结果值1和结果值2自动类型提升,统一类型
@Testpublic void test2() {char x = 'x';int i = 10;//如果其中有一个是变量,按照自动类型转换规则处理成一致的类型;System.out.println(true? x : i);//如果都是常量,如果一个是 char,如果另一个是[0~65535]之间的整数按 char 处理;System.out.println(true? 'x' : 10);System.out.println(false? 'x' : 97);//如果都是常量,如果一个是 char,另一个是其他,按照自动类型转换规则处理成一致的类型;System.out.println(true? 'x' : -1);}
原码、反码、补码
原码、反码、补码用特殊形式的二进制定点表示。
二进制形式和数据在内存中占用字节数有关(补0占位)
原码、反码、补码:二进制形式带有符号位。最高位是符号位,正数为0,负数为1
+9 00000000 00000000 00000000 00001001(int类型的正9)
在计算机中,所有的数据的计算都是以数据的补码进行计算的。
原码:显示数据 补码:底层正真进行数据操作的二进制数据 反码:是把原码和补码相互转换的中间量
数据操作的底层处理过程:计算
1.原始数据==》数据原码
根据原始数据确定二进制位数,不足补0
根据原始数据正负数确认符号位0还是1
2.原码=》反码
如果是正整数,反码与原码相同
如果是负整数,对原码逐位进行取反(除去符号位),符号位保持为1。
3.反码=》补码
正整数:补码与反码相同
负整数:补码=反码+1
-------------------——————————————
数据补码-----(对数据操作)---->结果是补码显示
4.补码=》反码
正整数:反码与补码相同
负整数:反码=补码-1
5.反码=》原码
正整数:原码与反码相同
如果是负整数,对反码逐位进行取反(除去符号位),符号位保持为1。
位运算符
针对二进制位进行操作的运算符
按位运算符& | ^ ~
按位与&:当俩位同时为1才为1按位或|,只要有一位为1即可返回1按位异或^:不同时为1,相同时为0 sout(3 ^ 28);sout(-3 ^ -28);按位非~:把数据的补码每一位(包括符号位)都取反
3->00000000 00000000 00000000 00000011(原)3->00000000 00000000 00000000 00000011(反)3->00000000 00000000 00000000 00000011(补)28->00000000 00000000 00000000 00011100(原)28->00000000 00000000 00000000 00011100(反)28->00000000 00000000 00000000 00011100(补)
00000000 00000000 00000000 00000011(3的补码)
& 00000000 00000000 00000000 00011100(28的补码)
结果补码 00000000 00000000 00000000 00000000,再转回原码也还是0,故
System.out.println(3 & 28);//0
-3 & -28
-3->10000000 00000000 00000000 00000011(原)-3->11111111 11111111 11111111 11111100(反)-3->11111111 11111111 11111111 11111101(补)-28 ->10000000 00000000 00000000 00011100 (原码)-28->11111111 11111111 11111111 11100011(反码)-28->11111111 11111111 11111111 11100100(补码)
11111111 11111111 11111111 11111101(-3补码)
& 11111111 11111111 11111111 11100100(-28补码)
结果补码11111111 11111111 11111111 11100100(补码)
结果补码转回反码 11111111 11111111 11111111 11100011(反码)
结果反码转回原码 10000000 00000000 00000000 00011100(原码),转为10进制就是-28,故
System.out.println(-3 & -28);//-28
左移运算符<<
二进制数往左移动指定的位数。符号位也跟着移动,低位出现空位需要补0【敏感位置也不怕】
左移看着直接乘就行了,112=28 * 2^2;-112=-28 * 2^2
System.out.println(28<<2);//112System.out.println(-28<<2);//-112
右移运算符 >>
二进制数往右移动指定的位数。符号位也跟着移动,高位出现空位,需要补和符号位相同的数据【0,1不定】
00000000 00000000 00000000 00011100(28补码)
00000000 00000000 00000000 00000011(右移3位,高位补0),所以结果是3,故:
System.out.println(28>>3);//3 28 /2^3=3...4
---------------------------------------------------------------
11111111 11111111 11111111 11100100(-28补码)
11111111 11111111 11111111 11111100(右移3位,高位补1,这是补码)
11111111 11111111 11111111 11111011(反码)
10000000 00000000 00000000 00000100(原码),故结果是-4
你要问我为什么商是负的因为要保证余数得是正的呀!
System.out.println(-28>>3);//-4 -28/ 2^3=-4...4
无符号右移运算符 >>>
二进制数往右移动指定的位数。符号位也跟着移动,高位出现空位,固定补0.
System.out.println(28 >>> 2);//7 28/2^2System.out.println(-28 >>> 2);//1073741817
11111111 11111111 11111111 11100100(-28补码)
00111111 11111111 11111111 11111001(无符号右移2位)
00111111 11111111 11111111 11111001(正数原码与反码相同,对应十进制1,073,741,817)