我正在使用以下代码在n维列表中查找唯一对象的一维列表(前一段时间为StackOverflow上的某人提供信用):
public static <T> List<T> getUniqueObjectsInArray(List<T> array) {
Integer dimension = getDimensions(array);
return getUniqueObjectsInArray(array, dimension);
}
private static <T> List<T> getUniqueObjectsInArray(List<T> list0, Integer dimension) {
List<T> list1 = new ArrayList<T>();
return getUniqueObjectsInArray(list0, list1, dimension);
}
private static <T> List<T> getUniqueObjectsInArray(List<T> list0, List<T> list1, int dimension) {
if (dimension < 1) return null;
if (dimension == 1) {
for (T listItem : list0) {
if (!list1.contains(listItem)) list1.add(listItem);
}
return list1;
} else {
for (Object listItem : list0) {
getUniqueObjectsInArray((List)listItem, list1, dimension - 1);
}
}
return list1;
}
它工作但我仍然得到一个'未经检查的分配'警告在以下行中将listitem
投射到List
getUniqueObjectsInArray((List)listItem, list1, dimension - 1);
现在我知道我可以添加@SuppressWarnings("unchecked")
,它会隐藏警告。但是如果没有这个警告,有没有一种根本不同的做法呢?如果有这样的警告,它到底是否重要?基本上好的代码还能包含警告吗?
我没有办法摆脱这种警告,因为你必须非常小心地声明并使用正确的通用数组类型。所以也许你决定忽略这个警告......
List<T>
声明正确描述了具有T类元素的一维数组。List<List<T>>
。List<List<List<T>>>
。您搜索的核心是递归getUniqueObjectsInArray(...)
方法。要摆脱警告,您必须确保拨打电话,例如List<List<List<String>>>
使用List<List<String>>
生成一个递归(内部)调用,并且维度比之前少一个,所以第一次尝试将是这样的:
public static <T,E> getUniqueObjectsInArray(List<T> array, List<E> results, int dimension) {
//...
for (T listItem : array) {
getUniqueObjectsInArray(listItem, results, dimension - 1);
}
}
这也行不通,因为编译器不允许你进行递归调用,因为他无法确保listItem是List。让我们试着告诉他:
public static <T,E> getUniqueObjectsInArray(List<List<T>> array, List<E> results, int dimension) {
//...
for (List<T> listItem : array) {
getUniqueObjectsInArray(listItem, results, dimension - 1);
}
}
现在他知道这是一个列表,但现在这还不够,因为现在你需要一个List<List<whatever>>
来调用getUniqueObjectsInArray(...)
。
你看,尝试做正确的泛型声明,以便编译器不会发出警告,如果可能的话,变得非常复杂。老实说,我没有办法避免警告,所以不要花太多时间,并添加@SuppressWarnings(“未选中”)。
这是因为您将对象“listItem”转换为“List”而没有泛型类型参数。
要摆脱这种情况,只需将通用类型参数添加到强制转换中,它就应该消除警告
(List<T>) listItem
好吧,我没有看到摆脱这个警告的方法,因为你执行向下铸造Object
到List
。
在您的情况下,列表中的项目可能是某个对象或列表,并且您没有可以描述此事实的泛型支持或其他语言构造。
因此,我在某些时候看到它需要执行转换操作。
不同的是,你现在拥有的东西并不安全:你究竟在这里确定的是什么
for (Object listItem : list0) {
getUniqueObjectsInArray((List)listItem, list1, dimension - 1);
}
listItem
是List的子类型?
您可以做的是尝试绑定您的通用类型和/或执行instance of
检查以确保铸造的正确性。
您隐式地在列表中投射所有项目。
static <T> T findAnItem(List<T> items){
return items.get(0);
}
List<Integer> ints = new ArrayList<>();
ints.add(0);
Object a = ints;
System.out.println(findAnItem((List<?>)a));
此示例将在没有警告的情况下进行编译,因为我没有将列表中的对象强制转换为Object旁边的任何对象。如果我将?
切换到Integer
,那么我会收到警告。