你知道这Java类型转换问题么?

来源:互联网 发布:网络电影还赚钱吗 编辑:程序博客网 时间:2024/06/03 20:26

开篇:首先让我们看段代码,并考虑它的正确性,之后会结合自己的研究说明其中原因

Stu[] c = (Stu[]) new Object[] { new Stu(), new Stu(),"1232131" };

一、基本数据类型转换原则

Java基本数据类型可以分为布尔型、字符型和数值型,而其中数值型又分为整型和浮点型;相对于数据类型,Java的变量类型为布尔型boolean;字符型char;整型byte、short、int、long;浮点型float、double。其中四种整型变量和两种浮点型变量分别对应于不同的精度和范围。

在Java中整型、实型、字符型被视为简单数据类型,这些类型由低级到高级分别为(byte,short,char)–int–long–float–double

1.自动类型转换

低级可以直接转换为高级

对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换

        byte b = 0;        int i = b;        long l = b;        float f = b;        double d = b;        // byte a=d; // 不能通过

如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,例如

    char c='c';    int i=c;    System.out.println(i);

输出:99

注:两个char型运算时,自动转换为int型;当char与别的类型运算时,也会先自动转换为int型的

2.强制类型转换

将高级变量转换为低级变量时,编译会不通过,但是我们可以使用强制类型转换来解决这个问题

float i=99;byte b=(byte)i;char c=(char)i;int f=(int)i;

注:虽然我们解决了编译问题,但是这种转换会导致溢出或精度的下降,因此不建议这么使用

3.基本类型和封装类的转换

我们可以通过如下方式通过一个基本类型获取一个封装类Integer

Integer a= new Integer(2);

当然我们也可以反过来获取int

int b=a.intValue();

其实这也不是什么转换,而是由于Integer是int的封装类看看iniValue()的源码就知道了

    private final int value;    public Integer(int value) {        this.value = value;    }    public int intValue() {        return value;    }

可以看到这里只是调用方法返回int类型

二、对象类型转换原则

java中的多态特性,让我们可能遇到编译通过但是运行时会抛异常。

我们知道Object是所有类的父类

    Object obj = new String();    String s =  obj;    // 编译时会报错

我们通过强制类型转换就可以解决编译问题

String s =(String)  obj; 

我们运行程序,编译通过,而且运行起来没有报错。

java中类型转换是有原则的:只有子类能强转成父类,父类转换成子类编译通过但是会在运行抛类型转换异常,而如果两种类型之间没有关系(两者无继承关系)那么强转的时候会编译不通过。如下面

    Object obj2 = new Object();    String ss = (String) obj2; // 编译通过,运行报类型转换异常

java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String

有的人会认为,这里s和ss指向的都是object类型,为什么会有上面的区别,其实我们可以通过代码很好理解。

System.out.println(obj.getClass());System.out.println(obj2.getClass());

输出如下:

class java.lang.Stringclass java.lang.Object

也就是说引用不能决定对象的最终类型,这个对象真正的类型应该是创建对象new的时候所对应的类型。

三、回到问题

OK,如果看到这里,你已经明白了开头的问题,那么祝贺你。如果你还有疑问,那么往下看。

Stu[] c = (Stu[]) new Object[] { new Stu(), new Stu(),"1232131" };

这个在执行的时候会抛类型转换异常,这里有人会认为,这里的”1232131”和Stu有什么关系?肯定错了啊!额,那我们试试下面的代码

Stu[] c = (Stu[]) new Object[] { new Stu(), new Stu()};

嗯,这里数组中的都是Stu类型的,一定没有问题了~~~~

但是结果是还是抛了同样的异常。可能还有部分人一头雾水,那么请看下面的执行情况

Object[] objs = new Object[] { new Stu(), new Stu() };System.out.println(objs.getClass());// 输出如下,objs是Object的数组类型class [Ljava.lang.Object;

其实,原因就和第二章中的末尾讲述的是同样的道理,new Object[],就认为类型是Object,父类转子类当然报错。反过来想想,Object数组可以存放任意类型的元素,如果引用类型不是Object数组,而是这里的Stu,如果objs中存在String类型,其与Stu是没有继承关系的,这违反了类型转换的原则。

但是,如果我们从objs中取出一个元素查看其类型,会发现它还是Stu类型的。那么如果需要像问题中那样将objs转成Stu[]可以通过以下方式

        Stu[] c = new Stu[objs.length];        for (int i = 0, j = objs.length; i < j; i++) {            c[i] = (Stu) objs[i];        }

更多源码:https://github.com/oDevilo/Java-Base

1 0
原创粉丝点击