- 自动类型转换
把子类对象直接赋给父类引用叫做向上转型,向上转型可以自动转换。
static class One { public void foo() { System.out.println("One"); } } static class Two extends One { public void foo() { System.out.println("Two"); } public void dosth(){ System.out.println("Two again"); } } public static void main(String[] args) throws Exception{ One t = new Two(); //向上转型,即父类引用指向子类对象,此时子类对象的类型为父类的类型 t.foo(); t.dosth();//编译错误 t = (Two)t; t.dosth();//编译错误 ((Two) t).dosth();//编译成功 }
- 强制类型转换
把指向子类对象的父类引用赋给子类引用叫做向下转型,要强制转换。
One one = new Two(); //向上转型,即父类引用指向子类对象,此时子类对象的类型为父类的类型
Two two = (Two)one; //向下转型,需强制转换,编译成功
One one2 = new One();
two = (Two)one2; //便衣成功,运行失败。报错信息为:java.lang.ClassCastException: com.xxx.One cannot be cast to com.xxx.Two
总结:
- 父类引用可以指向子类对象,子类引用不能指向父类对象。把子类对象直接赋给父类引用叫做向上转型,向上转型不用强制转型,如One o=new Two()。把指向子类对象的父类引用赋给子类引用叫做向下转型,要强制转型,如Two t = (Two)o。向上转型会丢失子类特有的方法,但是子类overriding父类的方法,子类方法有效。
- 对于强制类型转换,且是引用类型,如果是父类向子类转换,这种只牵扯到引用名义类型的转换,具体的内存没有什么变化。
- 数值类型转换
- 数据值类型按照范围从小到大为:byte,short,char,int,long,float,double
- 满足下列两种要求将执行自动类型转换:1.两种类型是兼容的;2.目的类型的范围比来源类型大。例如int类型比所有byte合法类型大,因此不要求显式强制类型转换。对于数字类型,整型和浮点型都是彼此兼容的,但是数字类型和字符类型和布尔类型是不兼容的,字符类型和布尔类型也不是互相兼容的。
- 自动类型转换不能满足所有的转换需求,比如int型变量赋值给byte型变量,这种转换不会自动进行,因为byte型比int型范围小。为了完成两种不兼容类型转换,需要用到强制类型转换。
byte b; int i = 257; double d = 32.13; b = (byte) i; System.out.println("i and b = " + i + " " + b); i = (int)d; System.out.println("d and i = " + d + " " + i); b = (byte)d; System.out.println("d and b = " + d + " " + b); byte e=(byte)130; System.out.println(e); /* * output i and b = 257 1 d and i = 32.13 32 d and b = 32.13 32 -126 */
short s = 1;
s= s + 1;//编译错误
short s1 = 1;
s1 += 1;
//上述陷阱是s = s + 1,s + 1会隐式转换为int型,把int型号赋给short,会造成类型缺失。而s1 += 1相当于s1 = (short)(s1 + 1)会把s1 + 1强制转换为short类型,就不会报错。
- 包装类之间转换
包装类之间不支持强制类型转换,需要调用Integer.valueOf()、Integer.parseInt()等方法。
Tips: Integer.parseInt(String s)将会返回int常量。
Integer.valueOf(String s)将会返回Integer类型,如果存在缓存将会返回缓存中已有的对象。即:如果s字符串对应的整数值在 -128~127之间,则解析出的Integer类型的对象是同一个对象;如果s字符串对应的整数值不在-128~127之间,则解析出的Integer类型的 对象不是同一个对象。