在Java中未经检查的分配

问题描述 投票:2回答:4

我正在使用以下代码在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"),它会隐藏警告。但是如果没有这个警告,有没有一种根本不同的做法呢?如果有这样的警告,它到底是否重要?基本上好的代码还能包含警告吗?

java generics casting
4个回答
1
投票

我没有办法摆脱这种警告,因为你必须非常小心地声明并使用正确的通用数组类型。所以也许你决定忽略这个警告......

  • 您的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(“未选中”)。


0
投票

这是因为您将对象“listItem”转换为“List”而没有泛型类型参数。

要摆脱这种情况,只需将通用类型参数添加到强制转换中,它就应该消除警告

(List<T>) listItem

0
投票

好吧,我没有看到摆脱这个警告的方法,因为你执行向下铸造ObjectList

在您的情况下,列表中的项目可能是某个对象或列表,并且您没有可以描述此事实的泛型支持或其他语言构造。

因此,我在某些时候看到它需要执行转换操作。

不同的是,你现在拥有的东西并不安全:你究竟在这里确定的是什么

for (Object listItem : list0) {
    getUniqueObjectsInArray((List)listItem, list1, dimension - 1);
}

listItem是List的子类型?

您可以做的是尝试绑定您的通用类型和/或执行instance of检查以确保铸造的正确性。


0
投票

您隐式地在列表中投射所有项目。

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,那么我会收到警告。

© www.soinside.com 2019 - 2024. All rights reserved.