【问题标题】:Diamond Operator; initialize paremeterized generic class钻石操作员;初始化参数化的泛型类
【发布时间】:2014-02-05 11:33:19
【问题描述】:

通常需要快速收集一组值才能对其进行迭代。我不想手动创建实例、添加项目或执行众所周知的构造函数初始化,即从数组的列表中创建一个集合 (Set<String> mySet = new HashSet<String>(Arrays.AsList("a", "b", "c"))),我想创建一个应该为我完成这项工作的函数。

事实上,我想提供泛型参数<S> 以用于集合类,我还想提供泛型参数<T> - Collection 的实际类型。

所以,我的第一个方法是:

public static <T extends Collection<S>, S> T initializeCollection(Class<T> concreteClass, S... objects) {
    T result;

    try {
        result = concreteClass.newInstance();
        for (S s : objects) {
            result.add(s);
        }

        return result;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}

这很好用,可以像这样使用:

LinkedList<String> myList = StaticHelper.initializeCollection(LinkedList.class, "a", "b");

HashSet<Integer> mySet = StaticHelper.initializeCollection(HashSet.class, 1,2,3,4,5);

从我现在测试的结果来看,这可以按预期工作。唯一的问题是验证器声明正在进行未保存的类型转换。使用 Set 的示例,验证器说

 Type safety: The expression of type HashSet needs unchecked conversion to conform to HashSet<Integer>

当我仔细查看 IDE 为我的函数声明的返回值时,它看起来像这样:

 <HashSet, Integer> HashSet my.namespace.helper.CollectionHelper.initializeCollection(Class<HashSet> concreteClass, Integer... objects)

因此验证者 ofc 认为,他必须执行从 HashSetHashSet&lt;Integer&gt; 的未保存转换。

但在我看来,函数的返回值是T,它几乎被定义为Collection&lt;S&gt;——而不是Collection

现在我想知道是否:

  • 我的函数存在问题,真的发生了未保存的类型转换
  • IDE 存在问题,未显示正确的 returnValue,因此验证器无法正常工作。

侧节点: 即使已经发布了一个好的替代方法(我已经在使用),我对这个问题的解决方案非常感兴趣。

public static <T extends Collection<S>, S> T<S> initializeCollection ...

或使用

... initializeCollection(HashSet<Integer>.class,...

显然是无效的语法,但基本上看起来像什么是必需的。

【问题讨论】:

  • 我认为问题在于编译器无法从 .class 文字中获取通用信息。因此,我认为在没有警告的情况下这样做是不可能的。

标签: java generics collections initialization


【解决方案1】:

不是一个直接的答案,但您可以通过以下方式使其更简单:

@SafeVarargs
public static <T extends Collection<S>, S> T initializeCollection(T collection, S... objects) {
    Collections.addAll(collection, objects);
    return collection;
}

然后调用它:

HashSet<Integer> mySet = initializeCollection(new HashSet<>(), 1, 2, 3, 4, 5);

【讨论】:

  • 那也不错。验证者也喜欢这种方法。 :)
  • 无警告(带有 SafeVarargs 注释)。我认为你的问题是 result = concreteClass.newInstance(); 返回一个原始类型,所以我认为你不能轻易摆脱警告......
  • 如果没有该注释,我没有任何警告。
  • @dognose 没有注释我得到Possible heap pollution from parameterized vararg type S
  • 我认为这还是更可取的,因为你没有异常/空问题。
猜你喜欢
  • 2019-03-16
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 2019-10-06
相关资源
最近更新 更多