java之ArrayList的toArray方法

ArrayList是Java在中使用频率非常高的一个方法。我们在使用ArrayList的时候,经常需要将ArrayList中的对象转换为一个数组。

java已经对ArrayList进行了很好的封装,只需要调用ArrayList的toArray方法就可以从ArrayList对象中提取存放的对象的数组。

ArrayList重载了如下两个toArray方法:

public Object[] toArray() {
         return Arrays.copyOf(elementData, size);
     }
public <T> T[] toArray(T[] a) {
         if (a.length < size)
             return (T[]) Arrays.copyOf(elementData, size, a.getClass());

         System.arraycopy(elementData, 0, a, 0, size);
         if (a.length > size)
             a[size] = null;
         return a;
     }

初学者在这两个方法的使用上获取会遇到一些困惑。下面结合笔者自己学习过程中遇到的困惑为大家详细介绍这两个toArray方法。

笔者在初学的时候在网络上看到过如下的简单代码

  ArrayList list1 = new ArrayList();
  System.out.println("size: " + list1.size());
  for(int i=0; i<20; i++){
   list1.add("hello");
  }
  String[] str = (String[])list1.toArray();

上面的代码先构造了一个ArrayList对象,然后往里面填了20个String对象,最后希望将ArrayList中的对象转换成一个数组。

执行上面的代码会报如下异常

[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

toArray()方法返回的数组为Object数组。上面的代码将Object数组强制转换为了String数组,属于将父类的引用强制转化为子类的引用。

java中,这种父类引用强制转化为子类引用只有在父类的引用指向的真实对象类型为所要强制转化的子类类型的时候,才不会报错。

下面举个小例子说明一下。

class Father{
	String name;
	int age;

}
class Son extends Father{
	String girlFriend;
}
class Daughter extends Father{
	String boyFriend;
}

public class test{
	public static void main(String[] args)
	{
		Father f = new Son();
		Son s = (Son)f;

		Daughter d = (Daughter)f;

		Father f2 = new Father();
		Son s2 = (Son)f2;

	}
}

String[] str = (String[])list1.toArray();报错很可能是由于toArray()方法返回的对象所指向的真实类型就是Object数组。

Arrays.copyOf(elementData, size)方法的源代码为


public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    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;
}
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}  

观察发现,当不指定拷贝的数据类型的时候,copyOf将直接使用数据源的数据类型进行对象的拷贝。

查看ArrayList的源代码可以看到elementData的定义为

private transient Object[] elementData;

因此,toArray()方法返回的对象的真实类型为Object[ ],因此无法将类型强制转化为String [],即便是ArrayList使用了泛型,也不能进行类似的强制类型转换。

我们一般通过toArray(T[] contents)方法将ArrayList转化为一个目标类型的数组

//toArray(T[] contents)调用方式一
public static Integer[] vectorToArray1(ArrayList<Integer> v) {
 Integer[] newText = new Integer[v.size()];
 v.toArray(newText);
 return newText;
}

//toArray(T[] contents)调用方式二。最常用!
public static Integer[] vectorToArray2(ArrayList<Integer> v) {
 Integer[] newText = (Integer[])v.toArray(new Integer[0]);
 return newText;
}

//toArray(T[] contents)调用方式三
public static Integer[] vectorToArray3(ArrayList<Integer> v) {
 Integer[] newText = new Integer[v.size()];
 Integer[] newStrings = (Integer[])v.toArray(newText);
 return newStrings;
}
public <T> T[] toArray(T[] a) {
         if (a.length < size)
             return (T[]) Arrays.copyOf(elementData, size, a.getClass()); # 方法二

         System.arraycopy(elementData, 0, a, 0, size); # 方法一和方法三
         if (a.length > size)
             a[size] = null;
         return a;
     }

其中,第一种方法和第三种方法都是利用了toArray(T[] contents)方法中的System.arraycopy语句进行数组的拷贝。由于System.arraycopy直接改变了

目标数组引用的内容,因此可以像方法一一样,不需要定义toArray方法的返回值,再将返回值返回,而是可以直接返回目标数组。

方法二则是使用了toArray(T[] contents)方法中Array.copyOf语句重新创建了一个目标类型的数组。

由于方法二的语句更加简洁,因此方法二更为常用。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-31 11:55:59

java之ArrayList的toArray方法的相关文章

黑马程序员——java基础 ArrayList集合基本方法演示

java基础 ArrayList集合基本方法演示 import java.util.ArrayList; import java.util.Iterator; public class ArrayListDemos { public static void main(String[] args) { // 创建一个新的容器 ArrayList al = new ArrayList(); al.add("abc1"); al.add("abc2"); al.add(&

java中List的toArray方法

把List转换成某种类型的数组,就拿String类型来做例子吧,有以下两种方式: //方法1,使用不带参数的toArray方法 String[] arr1=new String[list.size()]; list.toArray(arr);//此时arr就有了list中的值了 //方法2,使用带参数的toArray方法 String[] arr2=(String[])list.toArray(new String[0]);//参数含义的解释:要存储列表中元素的数组,如果它足够大的话:否则为此目

java 遍历arrayList的四种方法

package com.test; import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class ArrayListDemo {    public static void main(String args[]){        List<String> list = new ArrayList<String>();        list.add("luo

java 容器 arraylist 使用方法

1. ArrayList概述: ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口. ArrayList 继承了AbstractList,实现了List.它是一个数组队列,提供了相关的添加.删除.修改.遍历等功能. ArrayList 实现了RandmoAccess接口,即提供了随机访问功能.Rand

Java学习之道:ArrayList的使用方法

1.什么是ArrayList     ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和IList接口 灵活的设置数组的大小 2.如何使用ArrayList     最简单的例子: ArrayList List = new ArrayList(); for( int i=0;i<10;i++ ) //给数组增加10个Int元素 List.Add(i); //..程序做一些处理 List

深入理解java集合框架之---------Arraylist集合 -----添加方法

Arraylist集合 -----添加方法 1.add(E e) 向集合中添加元素 /** * 检查数组容量是否够用 * @param minCapacity */ public void ensureCapacity(int minCapacity){ modCount++; int oldCapacity = elementData.length; if(minCapacity > oldCapacity){ Object oldData[] = elementData; int newCa

Java之arrayList 方法二

类型不兼容的错误集合 package com.yuanzijian02; import java.util.ArrayList; public class ArrayList2 { public static void main(String[] args) { // TODO 自动生成的方法存根 ArrayList list = new ArrayList(); list.add("hello"); list.add(new Integer(2)); String str = (St

java的ArrayList使用方法详解

ArrayList是Java的链表类,在项目开发中十分常见,那么怎样对ArrayList进行添加.删除.修改.查询.遍历呢?本文将进行详细阐述. 工具/原料 java 一.ArrayList的添加方法 1 方法1:依次按照顺序向ArrayList中添加数据. 用法: 将a添加到list中 list.add("a"); #例子: 2 方法2:在第N个数据后面添加一个数据 用法: 在第1个元素后面添加E list.add(1, "E"); 注意:ArrayList中必须

【转】Java.util.ArrayList.set()方法实例

java.util.ArrayList.set(int index, E element) 替换与指定元素在此列表中指定位置的元素. 声明 以下是java.util.ArrayList.set()方法的声明 public E set(int index, E element) 参数 index -- 替换索引的元素. element -- 要被存储在指定位置的元素. 返回值 此方法返回在指定位置之前元素. 异常 IndexOutOfBoundsException -- 如果索引超出范围 例子 下