Java易错点2
如有理解错误的话,恳请大家指正!!!
数据类型转换
数据类型转换分为显示转换(强制类型转换)和隐式转换(自动转换)。
自动转换规则:
- 数据类型兼容
- 低级类型转高级类型(1、byte→short→int→long→float→double 2、char→int)
取值范围:
- byte: -2^7 ~ 2^7-1,即-128 ~ 127。1字节。
- short:-2^15 ~ 2^15-1,即-32768 ~ 32767。2字节。
- 有符号int: -2^31 ~ 2^31-1,即-2147483648 ~ 2147483647。4字节。
- 无符号int:0~2^32-1。
- long:-2^63 ~ 2^63-1,即-9223372036854774808 ~ 9223372036854774807。8字节。
- float:4字节。
- double:8字节
- char:2字节
- boole
上图的转换不会出现精度损失
示例代码 一
package com.wangscaler;
/**
* @author wangscaler
* @date 2021.06.09 14:37
*/
public class TestType {
public static void main(String[] args) {
long a = 2147483648;//此句有错误
System.out.println(a);
long b = 2147483648L;
System.out.println(b);
}
}
执行结果一
后两句的执行结果
-2147483648
解答一
在java中int的取值范围-2147483648 ~ 2147483647,而long a = 2147483648;
中先执行代码右边的数字,默认认为是整合类型的字面量,但数值大小超过了整数的取值范围,所以报错。然而long类型是可以放2147483648的,那怎么赋值?在后边加L,就默认认为他是Long类型的字面量,此时再赋值就不会出错。
00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000 --->long 2148483648
强转为int类型即截取后32位1000 0000 0000 0000 0000 0000 0000 0000其中首位为符号位,1为负数,此二进制数为反码。
转为原码(除符号位外取反加1)1000 0000 0000 0000 0000 0000 0000 0000--->值为-2147483648
这也是为什么整数的范围是-2147483648 ~ 2147483647(负数比正数多一位),因为10000000 00000000 00000000 00000000不表示-0,而是表示-N,无论是+0还是-0都是0没必要浪费位置,所以只有0000 0000 0000 0000 0000 0000 0000 0000才表示0
示例代码二
package com.wangscaler;
/**
* @author wangscaler
* @date 2021.06.09 14:37
*/
public class TestType {
public static void main(String[] args) {
int a = 1999999999;
float b = 1.0f;
double c = 1.0d;
System.out.println(a * b);
System.out.println(a * c);
short g = 222;
System.out.println(g / 7);
System.out.println(g / 7.0f);
int h = 6789;
System.out.println(h / 30);
System.out.println(h / 30.);
int i = 2147483642;
i += 1.0f;
System.out.println(i);
}
}
执行结果二
2.0E9
1.999999999E9
31
31.714285
226
226.3
2147483647
解答二
a*b的过程:a会自动转为float型参与计算,此时会有精度损失。
a*c的过程:a会自动转为double型参与计算,不会出现精度的损失。
g/7:g会自动转成int类型参与计算,所以结果是整型的31。
g/7.0f:g会自动转为float类型参与计算,结果是浮点数,可以达到预期的结果。
h/30:整型除以整型的结果还是整型,所以是226。
h/30.:h会自动转换成doublet型参与计算,所以结果是double的。
i+=1.0f:i会先转为float型参与计算,计算完毕后,在转回int类型,会出现精度的损失。
总结
综上所述,在程序中,应避免隐式转换,该强制转换的强制转换。
类的使用
重载:在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
重载规则:
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
重写:子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
方法的重写规则:
- 参数列表与被重写方法的参数列表必须完全相同。
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
- 父类的成员方法只能被它的子类重写。
- 声明为 final 的方法不能被重写。
- 声明为 static 的方法不能被重写,但是能够被再次声明。
- 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
- 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
- 构造方法不能被重写。
- 如果不能继承一个类,则不能重写该类的方法。
- 隐藏 :父类的静态方法和属性,在子类中出现,此时并不是重写,而是隐藏。调用时应该直接使用类名调用,避免混淆。
- 遮蔽:当一个声明遮蔽了另一个声明时,简单名将引用到遮蔽声明中的实体(这里不做示例)
- 遮掩:遮掩是指两个名字位于不同的名字空间的名字重用形式,名字空间包括:变量、包、方法或类型。
示例代码
People对象
package com.wangscaler;
public class People {
public String word = "people";
public static void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
Man
package com.wangscaler;
public class Man extends People {
public String word = "man";
@Override
public void sleep() {
System.out.println("打呼噜");
}
public static void eat() {
System.out.println("光盘行动");
}
}
main函数
package com.wangscaler;
/**
* @author wangscaler
* @date 2021.06.10 14:56
*/
public class TestClass {
public static void main(String[] args) {
People people = new People();
People pman = new Man();
Man man = new Man();
people.sleep();
pman.sleep();
man.sleep();
people.eat();
pman.eat();
Man.eat();
man.eat();
System.out.println(people.word);
System.out.println(pman.word);
System.out.println(man.word);
}
}
执行结果
睡觉
打呼噜
打呼噜
吃饭
吃饭
光盘行动
光盘行动
people
people
man
总结
可以看到在man函数中eat上 是无法使用注解 @Override
,因为他是隐藏,而不是重写。
为了避免混淆,应该直接使用类名调用,如上述的Man.eat();
至于遮蔽的情况如下:
String System;
System.out.println("a");
此时System就变成了我们自己定义的字符串,导致编译失败,所以我们定义变量的时候应该避免保留字和这些关键字。
关键字如下:
保留字 | 包相关 | 访问控制 | 变量引用 | 错误处理 | 程序控制 | 基本类型 | 类方法变量修饰符 |
---|---|---|---|---|---|---|---|
goto | package | protected | void | throws | break | boolean | abstract |
const | import | private | this | throw | continue | false | class1` |
public | super | try | return | float | extends | ||
catch | do | byte | final | ||||
finally | while | char | implements | ||||
if | double | interface | |||||
断言 | else | int | native | ||||
assert | for | short | new | ||||
instanceof | long | static | |||||
case | null | strictfpp | |||||
switch | true | synchronized | |||||
default | transient | ||||||
volatile |