java-day10
目录
代码中的一些条件、情况,在编译期间是不能确定的,只能在运行的时候确定。
早上
第一节课
o instanceof Person
表示引用o所指向的对象类型是不是属于Person
并不是引用o声明的类型是不是属于Person
【看右边new的对象而不看左边】
如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模/取余。如果对int型移动33位,实际上只移动了33%32=1位。如果对int型移动32位,实际上只移动了32%32=0位
第二节课
在操作数据的时候所使用的都是计算机中的补码
原码 | 反码 | 补码 | |
---|---|---|---|
正数 | 一致 | 一致 | 一致 |
负数(-1) | 1000 1110 | 1111 1110 | 1111 1111 |
除符号位按位取反 | 反码基础+1 |
位运算操作符
& | 与 | 1&1=1,1&0=0,0&0=0 |
---|---|---|
| | 或 | 1|1=1,1|0=1,0|1=1,0|0=0 |
^ | 异或 | 1^1=0,0^0=0,1^0=1,0^1=1 |
~ | 取反 | ~1-->1111 1110-->-2 |
//异或的应用
int a=1;
int b=2;
a=a^b;
b=a^b;
a=a^b;
print(a);
print(b);
第三节课
逻辑运算符
短路操作符,如果能根据左边第一个布尔表达式的结果推断整个表达式的结果,那么后面的布尔表达式就不会被计算了。
布尔表达式1 && 布尔表达式2 && 布尔表达式3
布尔表达式1 || 布尔表达式2 || 布尔表达式3
&& | 与运算符 |
---|---|
|| | 或运算符 |
短路与操作
短路或操作
思考1、&& 与 & 的区别
例如:作为位运算符
int a = 1;
int b = 1;
a&b
0000 0001
&
0000 0001
---------
0000 0001
例如:作为逻辑运算符
int a = 1;
int b = 5;
boolean result;
result = a>4 & (b++)>1;
&既可以作为二进制数字的位运算符,也可以作为布尔表达式中的逻辑运算符,但是作为逻辑运算符的时候,&并没有&&符合的那种短路的功能。
注意,这时候,无论任何情况下,都必须算完a>4的结果,和(b++)>1的结果,然后俩个结果在进行&运算,得出最终的结果,也就是这里没有&&这种短路功能的。
&&只能作为逻辑运算符,但是它会具备短路的功能。
注意,&&不能作为二进制数字的位运算符。
思考2、|| 与 | 的区别
与上面类似
条件操作符(三目运算符)
布尔表达式 ?值1:值2
布尔表达式为true时, 则返回值1
布尔表达式为false时,则返回值2
//上面代码的效果和这个是一致的
int score = 51;
String result;
if(score>=60){
result = "及格";
}else{
result = "不及格";
}
print(result);
下午
第一节课
基本类型之间的转换
隐式转换(Implicit) ,也是自动转换,在JVM运行期间,只要满足条 件,就可以自动完成类型转换的过程。一般是表示数据范围比较小的自动就可以转换为数据范围比较大的类型(基本类型)
byte a = 1; //8位
int b = a; //32位
//注意:这里在运行期间就自动完成了转换的过程。
显示转换(explicit),也是手动转换/强制转换,编译器发现类型无法自动转换的情况就会编译报错,这个时候我们确认无误后就可以进行类型强制转换,但是这里存在一定风险,将来运行这个代码时候可能会抛出类型转换异常。
int a = 100;
byte b = a; //编译报错,32位赋值给8位的数据
//把一个范围大的数据赋值给一个小的数据
//不允许的,也无法类型自动转换
//但是我们可以进行类型强制转换
int a = 100;
byte b = (byte)a;
//可能对数据的值造成印象
强制类型转换
随机数 [0,1)
随机数 [0,10)且是整数
随机数[25,46]
第二节课
引用类型之间的转换
隐式转换
Student s = new Student();
Object o = s;
//特点:子类类型的变量可以自动转化为(隐式)父类类型
//或者把中间变量去掉
Object o = new Student();
//特点:Object是父类型,Student是子类型
//父类型的引用可以指向子类型的对象
//在运行期间=右边的子类类型Student,可以自动转为=左边
//的父类类型Object
注意,虽然是引用类型之间的类型转换,但是和基本类型之间的转换还是保持一个规则,就是=号右边小范围类型数据,可以自动转为=号左边大范围类型的数据
显示转换(类型强制转换,简称强转)
Object o = new Student()new Student();
Student s = (Student)o;
编译通过和运行通过是两回事,二者关注点不同
编译器关注:等号两边的类型是不是一致,是不是有子父类的关系
例如Student s = (Student) o;
这句代码能不能通过,编译器看的是变量o声明的类型是Object,而变量s声明的类型是Student,这两个类型之间是有子父类关系的,所以编译通过
运行时候,JVM能不能成功执行Student s = (Student)o;它看到的是变量o在运行的时候所指向的对象是什么类型的,如果o所指向的对象具体的类型是Student类型或者Student类型的子类型,就可以成功,否则就会报错(类型转换异常)
另外,我们在做类型强制转换的时候还可以使用instanceof关键字进行判断,判断的目的是为了看看这个引用o是否真的可以转换为Student类型。
Object o = new Student( );
if(o instanceof Student){
Student s = (Student)o;
}
第三节课
类型转换的特点
Object o = new Student()new Student();
Student s = (Student)o;
一个变量声明完类型后,这个变量的类型不会改变,直到变量释放为止。上面虽然吧0强转为Student,并且把结果赋值给s,但o本身没有变化,o还是Object类型。o和s虽然类型不同,但是指向的对象相同。
int a = 100;
byte b = (byte)a;
//使用a的值的时候,由于=号俩边类型不一致,所以需要转换
//但是这个转换对变量a本身来讲,没有任何影响,在计算机的内存中,只是使用以下a的值,操作完之后的结果,在保存到变量b中,对a本身是没有任何改变和影响的。
//所以,在下面的代码中,任何地方,如果再使用到变量a,这变量a的类型依然是int
代码中的一些条件、情况,在编译期间是不能确定的,只能在运行的时候确定。
int a = (int)(Math.random()*10);
Object obj;
if( a%2==0){
obj = new CastTest();
}else{
obj = "Hello";
}
为什么需要类型转换
object o = new OperatorTest();
OperatorTest s = (OperatorTest)o;
o.能够调用的方法和访问的属性
s.能够调用的方法和访问的属性
这两种情况是不一样的,所以我们需要类型转换,因为很多时候使用当前的这类型调用不到我们想调用的方法或者实现,只能做类型转换,转成另-一个类型,然后就可以调用到这个方法了,类型大的调用的东西少,类型小的调用的东西多,通过类型的转换我们可以将大类型强制转化为小类型,从而调用更多的方法。