问题描述
我已经在学校用C ++编码了3年。我刚刚在2天前开始使用Java编写代码;我的问题是:制作泛型数组不好吗?什么是替代?
我很难过,除了做一些奇怪的事情,例如这个例子,我似乎无法建立一个通用数组:
//使用泛型类型实现MergeSort算法的类
//由Doina修订2014年1月
包装Sorting;
import java.lang。*;
公共类MergeSort {
//实际算法的包装方法
// T是将在运行时实例化的泛型类型
/ / elementas必须具有可比性
public static< T extends Comparable< T>> void sort(T [] a){
mergesort(a,0,a.length - 1);
}
//在伪代码之后的递归mergesort方法
private static< T extends Comparable< T>> void mergesort(T [] a,int i,int j){
if(j - i int mid =(i + j)/ 2;
mergesort(a,i,mid);
mergesort(a,mid + 1,j);
合并(a,i,mid,j);
}
//合并方法
//这里我们需要分配一个新的数组,但是Java不允许分配一个泛型类型的数组
// // As我们分配一个类型为Object []的数组,使用类型为
//这通常会生成一个警告,该警告被抑制
@SuppressWarnings(unchecked)
private static < T扩展了Comparable< T>> void merge(T [] a,int p,int mid,int q){
Object [] tmp = new Object [q - p + 1];
int i = p;
int j = mid + 1;
int k = 0; (a [i] .compareTo(a [j]) tmp($< = mid& j< = q){
tmp [k] = a [i ++];
else
tmp [k] = a [j ++];
k ++; (i while(i tmp [k ++] = a [i ++ ]。
} else {
while(j tmp [k ++] = a [j ++]; (k = 0; k } [b + k] =(T)(tmp [k]); //这是生成警告的行
//使用整数对象测试代码的主要方法
public static void main( String [] args){
Integer [] a = new Integer [5];
a [0] = new Integer(2);
a [1] = new Integer(1);
a [2] =新的整数(4);
a [3] =新的整数(3);
a [4] =新的整数(-1);
// T将被实例化为Integer,作为此调用的摘要
MergeSort.sort(a);
//在排序后打印结果
for(int i = 0; i< a.length; i ++)
System.out.println(a [i]的ToString());
$ / code>
解决方案
不是说它本身就是一个坏主意;它只是泛型和数组混合不好。
原因是协方差和不变性。数组是协变的(
)。 Integer []
是一个 Object []
因为 Integer
是 Object
,但泛型类是不变的( List< Integer>
即使 Integer
是<$ c $> a List< Object>
c> Object
您还必须处理未经检查的强制转换,这违反了泛型的全部目的。一个通用数组 - E [] foo =(E [])new Object [10];
- 不是类型安全的,不能在编译时强制执行。可能在运行时对它进行推理,但编译时检查泛型带到表中的编译时将在此丢失。
要直接回答这个问题,何时何地可能的情况是,您希望使用,因为它们播放非常很好地与泛型。
只是看着y我们提供的代码,我想用 List< T>
代替 T []
问题(我希望你传入一个 ArrayList
,因为这些操作在链接列表中会变得很昂贵)。
I've been coding with C++ in school for 3 years now. I've started coding in Java just 2 days ago; my question is:
Is it bad practice to make generic arrays? What would be the alternative?
I am stumped and I can't seem to make a generic array besides doing something weird such as this example:
//Class implementing the MergeSort algorithm with generic types
// Revised by Doina January 2014
package Sorting;
import java.lang.*;
public class MergeSort {
// Wrapper method for the real algorithm
// T is the generic type which will be instantiated at runtime
// elementas are required to be comparable
public static <T extends Comparable<T>> void sort(T[] a) {
mergesort(a, 0, a.length - 1);
}
// Recursive mergesort method, following the pseudocode
private static <T extends Comparable<T>> void mergesort(T[] a, int i, int j) {
if (j - i < 1) return;
int mid = (i + j) / 2;
mergesort(a, i, mid);
mergesort(a, mid + 1, j);
merge(a, i, mid, j);
}
// Merge method
// Here we need to allocate a new array, but Java does not allow allocating arrays of a generic type
// As a work-around we allocate an array of type Object[] the use type casting
// This would usually generate a warning, which is suppressed
@SuppressWarnings("unchecked")
private static <T extends Comparable<T>> void merge(T[] a, int p, int mid, int q) {
Object[] tmp = new Object[q - p + 1];
int i = p;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= q) {
if (a[i].compareTo(a[j]) <= 0)
tmp[k] = a[i++];
else
tmp[k] = a[j++];
k++;
}
if (i <= mid && j > q) {
while (i <= mid)
tmp[k++] = a[i++];
} else {
while (j <= q)
tmp[k++] = a[j++];
}
for (k = 0; k < tmp.length; k++) {
a[k + p] = (T) (tmp[k]); // this is the line that woudl generate the warning
}
}
// Main methos to test the code, using Integer Objects
public static void main(String[] args) {
Integer[] a = new Integer[5];
a[0] = new Integer(2);
a[1] = new Integer(1);
a[2] = new Integer(4);
a[3] = new Integer(3);
a[4] = new Integer(-1);
// T will be instantiated to Integer as a resutl of this call
MergeSort.sort(a);
// Print the result after the sorting
for (int i = 0; i < a.length; i++)
System.out.println(a[i].toString());
}
}
It's not that it's a bad idea per se; it's just that generics and arrays don't mix very well.
The reason is due to covariance and invariance. Arrays are covariant (Integer[]
is an Object[]
because Integer
is an Object
, but generic classes are invariant (List<Integer>
is not a List<Object>
even though an Integer
is an Object
).
You also have to deal with unchecked casts, which defeat the entire purpose of generics. The most common way to create a generic array - E[] foo = (E[]) new Object[10];
- is not type-safe and can't be enforced at compile time. It's possible to reason about it at runtime, but the compile-time checks which generics bring to the table are lost at that point.
To answer the question directly, where and when possible, you want to use Java Collections instead, as they play very nicely with generics.
Just glancing at your supplied code, I imagine that using List<T>
instead of T[]
would get you by most of your problems (and I would hope that you're passing an ArrayList
in since those operations can become expensive with a linked list).
这篇关于制作通用数组是否是不好的做法,以及替代方案是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!