Java数组与泛型

通常来说,泛型总是和数组无缘,比如下面这种用法:

Peel<Banana>[] peels = new Peel<Banana>[10];

上面的代码将无法通过编译,因为我们没法创建一个泛型数组。其原因为:由于类型擦除的原因,泛型参数所拥有的类型信息并不确定,但是数组总是要求持有确切的类型,以保证类型安全,但是我们可以参数化数组本身的类型:

import java.util.*;
import static net.mindview.util.Print.*;
class ClassParameter<T>
//使用泛型类将参数化数组
{
    public T[] f(T[] arg){
        return arg;
    }
}
class MethodParameter
{
    public static <T> T[] f(T[] arg){
        //使用泛型方法参数化数组
        return arg;
    }
}
public class ParameterizedArrayType
{
    public static void main(String[] args){
        Integer[] ints = {1,2,3,4,5};
        Double[] doubles = {1.1, 2.2, 3.3, 4.4, 5.5};
        Integer[] ints2 = new ClassParameter<Integer>().f(ints);
        print(Arrays.toString(ints2));
        //输出:[1, 2, 3, 4, 5]
        Double[] doubles2 = new ClassParameter<Double>().f(doubles);
        print(Arrays.toString(doubles2));
        //输出:[1.1, 2.2, 3.3, 4.4, 5.5]

        ints2 = MethodParameter.f(ints);
        print(Arrays.toString(ints2));
        //输出:[1, 2, 3, 4, 5]
        doubles2 = MethodParameter.f(doubles);
        print(Arrays.toString(doubles2));
        //输出:[1.1, 2.2, 3.3, 4.4, 5.5]
    }
}

ClassParamter通过泛型类参数化数组,MethodParameter.f()通过泛型静态方法参数化数组,两种方法都是可行的 ,只不过可以看出来,使用参数化类每次都要创建一个实例,明显参数化方法要简单的多,这个时候我就有一个问题了,既然存在类型擦除,那么参数化数组中能不能放入其他类型的数据呢:

doubles2[1] = 1L;//无法将Long转换为double类型

所以显然是不行的。
虽然我们没办法直接创建一个泛型数组,但是我们可以创建一个非泛型的数组然后将它转型:

import java.util.*;
//import static net.mindview.util.Print.*;
class BerylliumSphere{}
public class ArrayOfGenerics
{
    @SuppressWarnings("unchecked")
    public static void main(String[] args){
        List<String>[] ls;
        List[] la = new List[10];
        ls = (List<String>[])la;
        ls[0] = new ArrayList<String>();
        //ls[1] = new ArrayList<Integer>();
        //因为泛型的原因上面的代码将无法通过编译

        Object[] objects = ls;
        objects[1] = new ArrayList<Integer>();
        //由于Obejct是所有类的基类,所以上面的代码将可以通过编译

        List<BerylliumSphere>[] spheres = (List<BerylliumSphere>[])new List[10];
        for(int i=0; i<spheres.length; i++)
            spheres[i] = new ArrayList<BerylliumSphere>();
    }
}

上面这种方法都是建立在一个操作上的:

List<String>[] ls;

这个操作将不会引起警告,并且我们将创建具有斜边类型的数组。这一切都将归功于容器。
但是我们将不能直接创建泛型数组:

import java.util.*;
//import static net.mindview.util.Print.*;
public class ArrayOfGenericType<T>
{
    T[] array;//这样是可以的,因为T[]被擦除为Object[]
    @SuppressWarnings("unchecked")
    public ArrayOfGenericType(int size){
        //array = new T[size];
        //上面的代码将警告编译错误,因为泛型并不是确切类型
        array = (T[]) new Object[size];
        //但是我们可以创建一个Object数组,然后将他转型
    }
    //public <U> U[] makeArray(){
        //return new U[10];
        //上面的代码将警告编译错误,因为U并不是一个确切类型
    //}
}

通过参数化类,可以另辟蹊径的实现参数化数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值