[英]Is varargs of array possible in Java?
我試圖實現一種方法來合並任意數量的數組。
@SuppressWarnings("unchecked")
public static <T> T[] merge(T[]... arrs) {
int length = 0;
for (T[] arr : arrs) {
length += arr.length;
}
T[] merged = (T[]) new Object[length];
int destPos = 0;
for (T[] arr : arrs) {
System.arraycopy(arr, 0, merged, destPos, arr.length);
destPos += arr.length;
}
return merged;
}
它編譯,看起來沒有問題。 然后我測試了這種方法:
String[] a = {"a", "b", "c"};
String[] b = {"e", "f"};
String[] c = {"g", "h", "i"};
String[] m = merge(a,b,c);
盡管此代碼已成功編譯,但會引發異常:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at ntalbs.test.ArrayMerge.main(ArrayMerge.java:25)
代碼看起來合理且編譯成功,但不起作用,並在運行時引發異常。 您能解釋一下為什么此代碼不起作用嗎? 我想念什么?
這個問題與varargs無關。
如錯誤消息所述:您的方法創建並返回一個Object[]
,並將其強制轉換為String[]
。 但是Object[]
不是String[]
。 因此,例外。
查看Collection的源代碼(及其T[] toArray()
方法),以了解它基本上可以完成您想做的事情:創建一個T[]
類型的數組。
您可以通過T的類創建一個數組。 由於您傳入了對象,因此可以從其中之一獲取類型。 像這樣:
Class<T> clazz = arrs[0].getClass();
T[] arr = (T[]) Array.newInstance(clazz.getComponentType(), <length of all passed arrays>);
然后只需填充數組。
您的問題不是因為varargs。
因為排隊,
T[] merged = (T[]) new Object[length];
Object
數組不能轉換為String
數組。
采用,
T[] merged = (T[])java.lang.reflect.Array.newInstance(
arrs[0].getClass().getComponentType(), length);
注意:
正如@JB指出的那樣,這僅在您嘗試合並相同的數組類型時才有效。 如果要合並不同的數組類型,則必須找到所有數組共有的超級類型,並使用它代替arrs[0].getClass()
。
您不能將Object []轉換為String []。 您需要創建正確的運行時類型的實例。 為此,可以使用java.lang.reflect.Array#newInstance方法。 要獲得正確的類型,可以按如下所示將類參數添加到merge方法:
public static <T> T[] merge(final Class<T> arrayType, T[]... arrs) {
int length = 0;
for (T[] arr : arrs) {
length += arr.length;
}
@SuppressWarnings("unchecked")
T[] merged = (T[]) Array.newInstance(arrayType, length);
int destPos = 0;
for (T[] arr : arrs) {
System.arraycopy(arr, 0, merged, destPos, arr.length);
destPos += arr.length;
}
return merged;
}
這可以在沒有運行時異常的情況下執行:
String[] a = { "a", "b", "c" };
String[] b = { "e", "f" };
String[] c = { "g", "h", "i" };
String[] m = merge(String.class, a, b, c);
是的 , varargs適用於每種Java類型。 上面的異常是由行T[] merged = (T[]) new Object[length];
和varargs無關。
數組不是通用的。 我建議改用Collections框架。
如果您無法更改代碼結構,請嘗試類似的操作:
@SuppressWarnings("unchecked")
public static <T> T[] merge(T[]... arrays) {
int fullSize = 0;
for (T[] array: arrays) {
fullSize += array.length;
}
List<T> concatenatedList = new ArrayList<T>(fullSize);
for (T[] array: arrays) {
concatenatedList.addAll(Arrays.asList(array));
}
Class<T> targetType = (Class<T>)arrays
.getClass().getComponentType().getComponentType()
;
return concatenatedList.toArray(
(T[])Array.newInstance(targetType, concatenatedList.size())
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.