泛型与数组
概述:
首先java中数组是不支持泛型的,对于数组不支持泛型的原因,也有很多回答。这里有两个我认为比较好的回答,供大家参考泛型不支持数组的分析与泛型为什么不支持数组。以上两个回答还是比较深入,和透彻的。
我对于该问题的理解是:由于泛型只是在编译的时候,起到类型检测,及类型转换字节码的生成,也就是说具有泛型的java文件,最终生成的字节码会将泛型信息抹去,具体数据的引用类型一般都用object的来替代。并在对应的位置加上了类型转换代码。
例子1:
HelloWorld.java
public class HelloWorld{
public static void main(String args[]){
User<String> user = new User<String>();
user.setValue("weiwei");
System.out.println(user.getValue());
}
}
User.java
public class User<T> {
private T value;
public void setValue(T value){
this.value = value;
}
public T getValue(){
return value;
}
}
执行命令 javac 和 javap -c命令得到class字节码结果如下:
由上图第11 18 21行可知,编译过后11行数据类型为object类型 18行数据为object 类型21行为数据强转语句(String)object。
例子2:
public static void testRunGenerics(){
List<String> list1 = new ArrayList<String>();
List<Long> list2 = new ArrayList<Long>();
System.out.println(list1.getClass().equals(list2.getClass()));
}
以上代码运行结果为true。也就是说无论List还是List在运行期间都是类型List。
而java中规定数组在实例化的时候,需要确切的知道存放数据的类型(这样更方便的操作使用数组)。也就是说假设数组支持泛型,那么在编译成字节码的时候对于T[] = new T[10];最终会编译成Object[] objects=new Object[10],也就是说数组的具体类型在运行期间为object 类型,这时候对于数组内的元素操作可以强转也可以正常使用。但是编译器生成字节码的时候也有可能生成 (String[])(Objects) 这样的强转代码(出现转换错误)。
包装类实现泛型数组:
例子1 利用object数组间接实现泛型数组:
GenericArray.java 文件
package generics;
public class GenericArray<T> {
private Object[] values;
public GenericArray(int count){
values = new Object[count];
}
public void setValue(T t,int position){
values[position] = t;
}
public T getValue(int position){
return (T)values[position];
}
//注意此句代码调用会出错
public T[] getValues(){
return (T[])values;
}
}
测试代码:
public class Test {
public static void main(String[] args) {
GenericArray<String> generic=new GenericArray(10);
generic.setValue("wenwei1", 0);
generic.setValue("wenwei2", 1);
System.out.println(generic.getValue(0));
System.out.println(generic.getValue(1));
//
String[]content = generic.getValues();
}
}
执行结果:
分析:上面代码可以编译通过,而且我们使用GenericArray存储数据可以正常使用,但当我们调用其getValues则会出现强转类型错误(这种错误就是我们在概述中分析的编译器生成强转代码造成的)。
列子2 利用类型标识间接实现泛型数组:
GenericArray1.java文件
public class GenericArray1 <T>{
private T[] values;
public GenericArray1(Class<T> type,int length){
values= (T[])Array.newInstance(type, length);
}
public void setValue(T t,int position){
values[position] = t;
}
public T getValue(int position){
return (T)values[position];
}
public T[] getValues(){
return values;
}
}
测试代码:
public class Test {
public static void main(String[] args) {
GenericArray1<String> generic=new GenericArray1<String>(String.class,10);
generic.setValue("wenwei1", 0);
generic.setValue("wenwei2", 1);
System.out.println(generic.getValue(0));
System.out.println(generic.getValue(1));
String[]content = generic.getValues();
System.out.println(content[0]);
}
}
运行结果:
分析:上面代码可以编译通过,我们使用GenericArray存储数据可以正常使用,而且调用其getValues也不会出现强转类型错误,这种方式比较推荐(因为我们调用Array.newInstance()生成的数组是String[]类型的数组)。
补充说明:对于泛型数组,最简单的我们可以利用容器List来模拟实现!
希望对您有所帮助!