一、数据类型之间的转换
1.1 基本数据类型的自动类型转换(3种情况)
以下3种情况会发生自动类型转换:
-
当我们把存储范围小的类型的值(字面量值,变量值,表达式的值)赋值给存储范围大的类型的变量时
-
当多种类型混合运算时,会升级为它们当中最大的类型
-
当byte与byte,short与short,char与char,或者它们3个之间的运算,会升级为int
public class TestTypeChange1 {public static void main(String[] args) {int num = 'a';/*'a'的字面量值是char类型num变量是int类型char占2个字节,int占4个字节char的范围小,int范围大*/System.out.println("num = " + num);//num = 97double d = 1;/*1的字面量值是int类型d是doubledouble > int*/System.out.println("d = " + d);//d = 1.0}
}
public class TestTypeChange2 {public static void main(String[] args) {byte b = 1;short s = 2;/*编译器,看到字面量1和2的时候,如果它们赋值给byte,short时,会判断它们在不在byte,short范围,如果在他们范围内,可以正常赋值。*/char c = 'a';int i = 58;float f = 2.1f;System.out.println(b + s + c + i + f);//160.1}
}
public class TestTypeChange3 {public static void main(String[] args) {byte b1 = 1;byte b2 = 2;// byte b3 = b1 + b2;/*b1 + b2 升级为int,此时b1和b2是变量,每一个变量的范围是-128~127,计算可能超过byte范围,这里直接报错,不会检查值 在不在byte范围。byte相加用的是int类型指令,所以结果是int*/int b3 = b1 +b2;System.out.println("b3 = " + b3);char c1 = 'a';char c2 = '0';
// char c3 = c1 + c2;//c1+c2是int,int>char,无法赋值System.out.println(c1 + c2);//c1+c2虽然升级为int,但是println支持int结果// 97 + 48 = 145}
}
1.2 基本数据类型的强制类型转换(2种情况)
以下两种情况需要强制类型转换:
-
当我们把存储范围大的类型的值(字面量值,变量值,表达式的值)赋值给存储范围小的类型的变量时
-
有时候我们故意想让某个类型小的值按照大的类型计算时,也可以用强制类型转换
public class TestTypeChange4 {public static void main(String[] args) {int num = (int) 5.8;//代表报错的时候,光标移动到错误处,按快捷键Alt + Enter,会给你一些建议System.out.println("num = " + num);//num = 5byte b = (byte) 200;System.out.println(b);//-56/*200是int类型,二进制 00000000 00000000 00000000 11001000转为byte,只有1个字节,截取最后一个字节: 11001000(最高位是1,是负数)补码:11001000反码:11000111原码:101110008 + 16 + 32 = 56最高位1代表负数,-56人工用权值相加法时,需要用原码算。计算器不用这么麻烦,直接根据补码就可以得到结果*/byte b2 = (byte) 128;/*128是int类型,二进制 00000000 00000000 00000000 10000000转为byte,只有1个字节,截取最后一个字节: 10000000它需要单独记 -128*/}
}
public class TestTypeChange5 {public static void main(String[] args) {int x = 1;int y = 2;System.out.println(x / y);//0 结果是int类型System.out.println((double)x/y);//0.5 把x的值1升级为double,double/int结果是doubleSystem.out.println((double)(x/y));//0.0}
}
1.3 特殊的String
public class TestString {public static void main(String[] args) {System.out.println("a" + 'b' + 'c');//abc/*"a" + 'b' 是拼接 得到 "ab""ab" + 'c' 还是拼接,得到"abc"*/System.out.println('a' + 'b' + 'c');//294 = 97 + 98 +99System.out.println('a' + 'b' + "c");//97 + 98 = 195//195 +"c" 拼接/*凡是+的左右出现字符串,+就是拼接,结果还是字符串凡是+的左右都不是字符串,+就是求和,用数字来算*/}
}
public class TestString2 {public static void main(String[] args) {int num = 15;String str = num + "";//""是一个空字符串,没有任何字符System.out.println(str);String str2 = "15";
// int num2 = (int)str2;//强制转换不可以int num2 = Integer.parseInt(str2); //后面要学习的方法}
}
二、运算符
Java为程序员设计了非常多的运算符,为基本数据类型设计这些运算符。
2.1 运算符的分类
1、按照功能划分:
-
算术运算符:加(+),减(-),乘(*),除(/),模(就是取余数,%),自增(++),自减(--)
-
赋值运算符:=
-
赋予变量一个值
-
-
关系运算符:大于(>),小于(<),等于(==),不等于(!=),大于等于(>=),小于等于(<=)
-
逻辑运算符:逻辑与(&,且),逻辑或(|,或),逻辑异或(^),逻辑非(!,否),短路与(&&),短路或(||)
-
条件运算符:条件? 结果1 : 结果2
-
位运算符:左移(<<),右移(>>),无符号右移(>>>),按位与(&)、按位或(|),按位异或(^),按位取反(~)
-
结合的运算符:+=,-=,*=,/=,%=等
2、按照操作数的个数划分
-
单目运算符:一元运算符,只需要一个操作数,例如:++,--,~,!等
-
三目运算符:三元运算符,条件? 结果1 : 结果2
-
双目运算符:二元运算符,除了单目和双目,都属于它
3.2 算术运算符
3.2.1 加减乘除模
加(+):
有字符串参与就是拼接,结果也是字符串;
没有字符串参与就是求和,结果就是数字;
减(-):正常减
乘(*):正常乘
除(/):
整数 / 整数 结果一定是整数
被除数 / 除数,如果都是整数的话,那么除数不能为0,否则会发生ArithmeticException异常
如果是小数的话,那么除数为0,结果是Infinity 无穷
模(就是取余数,%):
被模数 % 模数 的结果的正负号与被模数相同
public class TestDivide {public static void main(String[] args) {//System.out.println(1/0);//编译通过,运行会发生ArithmeticException算术异常System.out.println(8.0 /2.4);System.out.println(8.0 / 0.0);//Infinity 无穷}
}
public class TestMod {public static void main(String[] args) {System.out.println(8 % 3);//商是2,余数是2System.out.println(3 % 8);//商是0,余数是3System.out.println(8 % -3);//商是-2,余数是2//被除数 ÷ 除数 = 商 ... 余数//被除数 = 除数 x 商 + 余数System.out.println(-8 % 3);//商是-2,余数是-2System.out.println(-8 % -3);//商是2,余数是-2System.out.println("====================");int num = 516;//3位数 000 - 999System.out.println("个位:" + num % 10);System.out.println("十位:" + num / 10 % 10);System.out.println("百位:" + num / 100);}
}
3.2.2 自增自减
自增(++):让自增变量本身+1
自减(--):让自增变量本身-1以自增为例:(1)当自增表达式独立一个语句时,例如:a++; ++a; 此时++在前在后没有区别,都是自增变量+1(2)当自增表达式与其他的计算合为一个语句时,就有区别了++在前,先自增再取值计算++在后,先取值放一边,然后自增,最后用取出来的值计算
案例1
public class TestIAdd {public static void main(String[] args) {int a = 1;a++;System.out.println("a = " + a);//a=2a--;System.out.println("a = " + a);//a=1}
}
案例2
public class TestIAdd2 {public static void main(String[] args) {int a = 1;//以下写法++。--在前在后没区别a++;System.out.println("a = " + a);//a=2++a;System.out.println("a = " + a);//a=3a--;System.out.println("a = " + a);//a=2--a;System.out.println("a = " + a);//a=1}
}
案例3
public class TestIAdd3 {public static void main(String[] args) {int a = 1;int b = a++;//自增不是独立的运算,与赋值在一起/*(1)处理a++, 先取a的值1放一边(用专业的话说,放操作数栈),然后a自增1,a=2, 总结:先取值后自增(2)把刚才取出来的值,赋值给b*/System.out.println("a = " + a);//a=2System.out.println("b = " + b);//b=1int c = ++a;/*(1)处理++a, 先对a自增1,a=3,然后取a的值3放一边(用专业的话说,放操作数栈) 总结:先自增再取值(2)把刚才取出来的值,赋值给c*/System.out.println("a = " + a);//a=3System.out.println("c = " + c);//c=3}
}
案例4
public class TestIAdd4 {public static void main(String[] args) {int a = 1;System.out.println(a++);//1 先取值1放一边,然后自增a=2System.out.println(a);//2System.out.println(++a);//3 先自增1,a=3,再取值输出System.out.println(a);//3}
}
案例5
public class TestIAdd5 {public static void main(String[] args) {int a = 1;a = ++a;/*(1)先处理++a, a先自增1,a=2,然后取a的值2放一边(2)赋值 a=2*/System.out.println("a = " + a);//a=2a = a++;/*(1)先处理a++, 先取a的值2,放一边,然后a要自增1,a=3(2)赋值 a=2*/System.out.println("a = " + a);//a=2}
}
案例6
public class TestIAdd6 {public static void main(String[] args) {int a = 1;int b = a++ + ++a * a++;/*(1)先处理 a++ 先取a的值1放一边, 紧接着a自增为2(2)处理 ++a 先对a自增1,a=3,然后取a的值3放一边(3)因为要先算乘法,乘法需要两个操作数,处理a++ 先取a的值3放一边, 紧接着a自增为4(4)算乘法 3 * 3 = 9(5)算加法 1+9=10(6)赋值 b = 10*/System.out.println("a = " + a);//a=4System.out.println("b = " + b);//b=10}
}
3.3 赋值运算符(掌握)
3.3.1 独立的赋值运算符
赋值运算符:=
注意:
-
=的左边一定是一个变量,不能是一个字面量值或表达式。
-
a + b = c c = a + b 数学中上面两个式子是一样的,但是编程中完全不同a = 1 1 = a 数学中上面两个式子是一样的,但是编程中完全不同
-
类似的:自增自减也是只能是变量自增自减,不能是字面量值或表达式自增自减
a++ 对
++a 对
2++ 错
++2 错
(a+b)++ 错
-
=右边的结果的类型 必须 小于等于 = 左边的变量的类型,否则就需要强制类型转换。
-
赋值运算优先级比较低,都是最后算赋值。
-
赋值操作,一定是把"=右边的值" 给 "=左边的变量"。
public class Exercise4 {public static void main(String[] args) {int a = 1;int b = 2;/*方案一:必须掌握的方案,适用于所有数据类型,包括后面的引用数据类型*/int temp = a;//把a变量的值 倒入 temp这个杯子a = b; //把b变量的值 倒入 a这个杯子b = temp; //把temp变量的值 倒入 b这个杯子System.out.println("temp = " + temp);//temp=1System.out.println("a = " + a);//a=2System.out.println("b = " + b);//b=1}
}
public class Exercise4_2 {public static void main(String[] args) {int a = 1;int b = 2;//方案二:了解//有缺陷,对数据类型,和数据值的范围有要求a = a + b; //新的a = 旧的a + 旧的bb = a - b;//新的b = 新的a - 旧的b = 旧的a + 旧的b - 旧的b = 旧的aa = a - b;//更新的a = 新的a - 新的b = 旧的a + 旧的b - 旧的a = 旧的bSystem.out.println("a = " + a);//a=2System.out.println("b = " + b);//b=1}
}
3.3.2 算术运算符结合赋值运算符
+=
-=
*=
/=
%=
-
这些运算符的右边是一个整体,赋值最后算
-
当表达式计算完的结果类型大于左边变量的类型时,会强制类型转换,需要警惕
溢出或损失精度
public class TestAssign {public static void main(String[] args) {int a = 1;a += 1;// a = a + 1;System.out.println(a);//a=2int b = 1;a *= a + b;//a = a * (a+b) = 2 * (2+1) = 6System.out.println("b = " + b);//b=1System.out.println("a = " + a);//a=6byte b1 = 127;byte b2 = 2;
// b1 = b1 + b2;//错误,b1+b2会升级为intb1 += b2;// b1 = (byte)(b1 + b2);System.out.println("b1 = " +b1);//b1 = -127/*b1+b2=129 的二进制 00000000 00000000 00000000 10000001截断 10000001 符号位是1,是负数如果是计算器看结果,10000001(补码)直接放到二进制的位置即可如果是人工计算,用权值相加法,需要换算原码10000001(补码)10000000(反码)11111111(原码)最左边的1,表示负数剩下的1,权值相加法 11111111+2+4+8+16+32+64=127*/}
}
3.3.3 哪些运算符会改变变量的值?
a++
++a
a--
--a
a=?;
a+=?;
....
变量出现在赋值运算符的左边
3.4 关系运算符
关系运算符:大于(>),小于(<),等于(==),不等于(!=),大于等于(>=),小于等于(<=)
关系运算符又称为比较运算符。
这些运算符有要求,比较关系的两个数的类型必须一致,不一致要先统一
这些运算符的结果:true 或 false
public class TestCompare {public static void main(String[] args) {int a = 1;int b = 2;System.out.println(a > b);//falseSystem.out.println(a < b);//trueSystem.out.println(a >= b);//falseSystem.out.println(a <= b);//trueSystem.out.println(a == b);//falseSystem.out.println(a != b);//trueSystem.out.println("==============================");System.out.println(a = b);//把b的值赋值给aSystem.out.println("a = " + a);//a=2System.out.println("b = " + b);//b=2//注意,= 和 == 的区别}
}
3.5 逻辑运算符
逻辑与(&,且),逻辑或(|,或),逻辑异或(^),逻辑非(!,否),短路与(&&),短路或(||)
首先,逻辑运算符的操作数必须是boolean值true或false。
其次,它们的计算结果也是boolean值true或false。
逻辑与(&,且): 只有....才.... 只有两边都是true,结果才为true 两个同时成立
true & true 结果是true
true & false 结果是false
false & true 结果是false
false & false 结果是false
逻辑或(|,或): 只要....就.... 只要有一边为true,结果就为true 成立一个就可以
true | true 结果是true
true | false 结果是true
false | true 结果是true
false | false 结果是false
逻辑异或(^):只有....才.... 只有两边不同,一个为true,一个为false,结果才为true 两个只能成立1个
true ^ true 结果是false
true ^ false 结果是true
false ^ true 结果是true
false ^ false 结果是false
逻辑非(!,否):它是一个一元运算符,只有1个操作数
!true 结果是false
!false 结果是true
短路与(&&)
true && true 结果是true
true && false 结果是false
false && ? 结果是false
当左边为false时,右边不看,结果直接是false,所以效率比较高。
开发中更多的用下面这个。
短路或(||)
true || ? 结果是true
false || true 结果是true
false || false 结果是false
当左边为true是,右边不看了,结果直接是true,所以效率比较高。
开发中更多的用下面这个。
public class TestLogic {public static void main(String[] args) {System.out.println(true & true);System.out.println(true & false);System.out.println(false & true);System.out.println(false & false);System.out.println("==================");//Alt + J,向右向下选择相同的符号或单词,修改后用Esc退出多行编辑模式System.out.println(true | true);System.out.println(true | false);System.out.println(false | true);System.out.println(false | false);System.out.println("==================");System.out.println(true ^ true);System.out.println(true ^ false);System.out.println(false ^ true);System.out.println(false ^ false);System.out.println("==================");//表示年龄的要求是在[18,35]int age = 37;// 数学中 18<=age<=35
// System.out.println(18 <= age <= 35);//18 <= age 结果是 true// true <= 35 两边类型不同,无法统一System.out.println(18 <= age & age <= 35);//false}
}
public class TestLogic2 {public static void main(String[] args) {boolean flag = true;System.out.println(!flag);//false//判断a变量是不是偶数int a = 8;System.out.println("a是不是偶数?" + (a%2==0)); //能被2整除吗System.out.println("a是不是偶数?" + !(a%2!=0));//不是奇数吗}
}
3.6 条件运算符(掌握)
条件运算符:条件? 结果1 : 结果2
规则:如果条件成立,条件结果为true,那么整个表达式的结果取结果1的值,否则就取结果2的值。
要求:最终这个条件运算符计算的结果要么 赋值给变量,要么参与其他运算(输出、拼接等),不能独立存在。
public class TestCondition {public static void main(String[] args) {int x = 4;int y = 3;// x > y ? x : y;//错误,条件运算符计算完的结果没有用起来// int max;// x > y ? max = x : max = y;//错误int max = x > y ? x : y;System.out.println("max = " + max);System.out.println("最大值是" + (x > y ? x : y));System.out.println(x > y ? x : y);System.out.println("===================");int m = 5;int n = 4;int p = 6;int biggest = m>n?m:n;//biggest是m,n中的最大值biggest = biggest > p ? biggest : p;//3个数中的最大值System.out.println("biggest = " + biggest);/*对于程序员的要求:(1)完成功能(2)考虑可读性(3)考虑效率,性能(内存和时间)先保证(1)能实现,在(1)已经比较轻松的情况下,想想(2)(1)(2)都没问题,再想(3)*/}
}