Java强制类型转化和自动类型转化

首先Java的数据类型分为基本数据类型和引用数据类型,所以关于强制类型转化和自动类型转化也分别从基本数据类型和引用数据类型来讨论。

基本数据类型

8大基本数据类型:byte、short、int、long、double、float、char、boolean

自动类型转化

看几个例子:

long a=100;//整数型字面量100默认被当作int类型来处理,这里是自动类型转换
long c=300L;//300L本身就是Long类型,不是自动类型转换
long d=2147483648;//编译出错,原因:整数型字面量2147483648默认看成int类型,但是int类型的最大值是2148483647,,一上来就超出范围了。

自动类型转化:Java中基本数据类型的小容量类型可以自动转化为大容量的类型。像如上的long a=100;就是占4个字节的int类型转化为占8个字节的long类型,这种操作被称为自动类型转化。

强制类型转化

看几个例子:

long x=100L
int y=x;//编译出错
int y=(int)x;//强制类型转换,但是可能会损失精度,比如超过2148483647 
String s="111";
int x=(int)s;//报错,String不是八大基本数据类型。

像如上的int y=(int)x;就是占8个字节的long类型转化为占4个字节的int类型,这种操作被称为强制类型转化。

引用数据类型

在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需要强制转换。

看个例子:(下面的例子,注意区分对象和类)

//父类
public class Father {
    public void doSome(){
        System.out.println("父类doSome");
    }
}
//子类
public class Son extends Father{
    public void doSome(){
        System.out.println("子类doSome");
    }
    public void doOther(){
        System.out.println("子类doOther");
    }
}
//测试类

public class TestExtend {
    public static void main(String[] args) {
        Father father = new Son();//自动类型转化,向上转型
        Son son= (Son) father;//father对象本质是Son类型,可以强制类型转化为Son类型,就是恢复成Son类型
        son.doSome();
        son.doOther()
    }
}

运行结果:

这种情况是编译正确且运行正确的,Father father = new Son();是父类的引用指向了子类。(引用的概念很重要呀:Java里面类似C的指针一样的东西,比如:类名 引用名=new xxx();)。并且最后的son对象可以调用Son类的doSome和doOther方法。

再来看第二种情况

public class TestExtend {
    public static void main(String[] args) {
        Father father = new Father();
        Son son= (Son) father;//father对象本质就是Father,想要强制类型转化为Son,编译可以通过,但是运行阶段会报错。
        son.doOther();
        son.doOther();
    }
}

这种情况下代码不提示错误,编译可以通过,但是运行阶段会报错:Father不能转化为Son

解释

Father father = new Son();这种情况,类的本质还是Son,用Father类型的引用来指向,这个时候会限制我们对象的功能,因为Father类型的指针的作用范围是有限的,只能指向子类继承自父类的那部分,比如这个时候不能写father.doOther();如下:

father.doOther()被限制了,如果想要还原怎么办?将其对象类型还原,即 Son son= (Son) father;强制类型转化回去。

可以执行father.doSome(),但是执行的结果是什么呢??

结果一定是

这其实就是多态。可以参考Java的继承和多态,真的明白它的实际用处吗?_source code August的博客-CSDN博客

多态其实就是编译阶段和运行阶段是两种形态,编译阶段编译器认为father对象是Father类型,但它的本质是Son类型,运行阶段真正执行的也是Son类的方法。

那么为什么第二种情况会报错呢?我多次提到“本质”和“限制”,值得一提的是,Java对象被new出来之后,他在内存中的本质就不会改变,我们只能通过指针在编译阶段去“限制”它的功能,而运行阶段,它还是它自己。

总结

总结一下:编译器在编译时只会检查类型之间是否存在继承关系(还有接口和实现),有则通过;而在运行时就会检查它的真实类型,是则通过,否则抛出ClassCastException异常。

也就是说在继承中,子类可以自动转型为父类,但是父类强制转换为子类时只有当引用类型真正的身份为子类时才会强制转换成功,否则失败

instanceof

对于类似这种Father father = new Father();Son son= (Son) father;编译可以通过,但是运行阶段会报错的情况,在运行代码之前我们发现不了错误,所以为了避免出现这种情况,在向下转型的时候,使用instanceof运算符,代码可以这么写:

Father father = new Father();
if(father instanceof Son){
    Son son= (Son) father;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值