600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Java数组 强制类型转换

Java数组 强制类型转换

时间:2022-02-22 21:16:00

相关推荐

Java数组 强制类型转换

数组的强制类型转换

数组的强制类型转换数组类型转换的问题为什么会出现在我脑海中?

数组的强制类型转换

最重要的是!!!最开始的时候声明的数组类型!!!

最重要的是!!!最开始的时候声明的数组类型!!!

最重要的是!!!最开始的时候声明的数组类型!!!

例如:

Object[] objects = new Object[2];Object[0] = "hello";Object[1] = "world";Object[] objects1 = {"kkkk", 3434}System.out.println(objects.getClass());System.out.println(objects1.getClass());System.out.println(objects[0].getClass());System.out.println(objects[1].getClass());System.out.println(objects1[0].getClass());System.out.println(objects1[1].getClass());

class [Ljava.lang.Object;

class [Ljava.lang.Object;

class java.lang.String

class java.lang.String

class java.lang.String

class java.lang.Integer

根据实验,一开始就声明为String数组,可以在需要时自动转为Object数组,之后可以通过强制类型转换再转回String数组

但是,如果一开始就声明为Object数组,那么,即便这个数组中存放的全部是String对象,也是不能转换为String数组的!!!

数组类型转换的问题为什么会出现在我脑海中?

先上代码:

public class Base {public ArrayList<String> data;public String[] getData() {return (String[])data.toArray();}public void setData(String[] data) {this.data = new ArrayList<String>(Arrays.asList(data));}}

遇到的问题如下:当调用setData设置好data之后,紧接着getData()将会抛出一个类型转换异常java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;提示不能将String数组强转为Object数组,这是为什么呢???明明我是String泛型的ArrayList呀,怎么一toArray()就成了Object数组了呢???而且这个Object数组为什么不能强转成String数组呢?我自己用String数组转换成Object数组之后,是可以转回String数组的呀,为什么这里就转不回去,而且报错了呢??????

带着问题的 我 和 源码 展开了“深入”交流

参照源代码的时候发现,首先,Arrays.asList(data)依然返回的是泛型,也就应该是String[]。因此,上述ArrayList的那个构造方法,传入参数时,应该是String[]。

这就神奇了,既然我参数传入的时候还是String数组,为什么data.toArray();就成了Object数组了呢???难道是data.toArray()这个方法在搞鬼??

带着疑问,继续阅读源码,发现这个无参的toArray()方法转向了Arrays类的静态方法Arrays.copyOf(elementData, size);,之后又转向了copyOf的三参数重载方法:

class ArrayList {... ...public Object[] toArray() {return Arrays.copyOf(elementData, size);}}

class Arrays {... ...public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());}... ...public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}}

那么问题来了,这个作为参数传入的ArrayList的实例域elementData实际上是什么类型的数组呢?这个3个参数的copyOf又干了什么呢???

首先,看看这个三参数copyOf()函数干了什么:我们不妨假设elementData.getClass()依然是String数组。如果这样的话,应该会调用?:表达式的第二个代码:

: (T[]) Array.newInstance(newType.getComponentType(), newLength);

Array.newInstance()返回的是Object引用类型,并最终导向native代码。虽然我不清楚它做了什么,但是有两点可以确定:

源代码既然在强转的时候没有报错,说明该方法的返回的实际对象一定是T子类的数组。而T类型是什么呢?因为假设传入的是String数组的Class对象,且这里String除了Object之外没有超类了,所以T必为Object类型;很显然冒号左侧才是新建了一个Object数组,那冒号右面猜测应该是建立了一个泛型数组,但是暂时不确定。在返回到二参数copyOf()方法中的时候,这里的T数组我们已经假设为String数组(因为我们假设elementData是String数组),在将Array.newInstance()产生的数组强转为T数组(String数组)时没有报错,说明,Array.newInstance()产生的必然是String数组。

也就是说,在二参数copyOf()返回时,返回类型必然和elementData是同一类型,那我们又假设elementData是String数组,最后toArray()返回就不是String数组吗???怎么之后强转会出错呢?

那只能说明假设错了!!!!!

那说明elementData已经不是String类型了!那是什么时候变的呢?我们来到了它的构造方法:

class ArrayList {......public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}}

看到这个方法的第4、5行,已经当场气死~原来在构造方法的时候,就已经将不是Object数组的数组转成了Object数组,并存放在elementData中,而无参的toArray()方法并没有对其特殊处理,直接返回了一个Object数组(虽然里面元素仍然是String)。

所以,如果要返回泛型数组,该怎么办呢?

答案是:调用带参的toArray()方法!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。