具有通用 return 类型的 vararg 方法中的 @SafeVarargs

@SafeVarargs in vararg method with generic return type

我下面的 query 方法使用 org.hibernate.Session 有助于查询我的持久层。这是方法代码:

public class Persister{

    public static <E> List<E> query(Class<E> c, E... exampleEntities){
        try(Session session = openSession()){
            final Criteria criteria = session.createCriteria(c);
            for(E e : exampleEntities){
                final Example example = Example.create(e);
                criteria.add(example);
            }

            @SuppressWarnings("unchecked")
            final List<E> list = criteria.list();
            /*
             * Empty loop technique ensures all elements in list are of type E
             * otherwise a ClassCastException is thrown. Inspired by
             * "Java Generics" section 8.2
             */
            for(E e : list);
            return list;
        }
    }

    //other methods ommitted
}

它引发了以下警告:

Type safety: Potential heap pollution via varargs parameter exampleEntities

在这种情况下使用 @SafeVarargs 注释是否安全?

据我了解,只要我不使用 exampleEntities 初始化本地 Object[],就可以了。但这似乎不对。

此方法java.util.Collections.addAll mentioned in the Java Specification §9.6.3.7方法类似,注解为@SafeVarargsThis answer 讨论警告,说一般来说下面的代码是安全的:

@SafeVarargs
void foo(T... args) {
    for (T x : args) {
        // do stuff with x
    }
}

但是我的 query 方法的形式是:

<T> List<T> query(T... args) {
    Foo foo = new Foo();
    for (T x : args) {
        foo.add(x);
    }
    return (List<T>) foo.list();
}

那么,是否存在 @SafeVarargs 注释不安全的情况?

是的,您可以使用 @SafeVarargs。能否使用@SafeVarargs取决于你如何使用varargs参数exampleEntities。如果你依赖它的实际运行时类型是 E[],那么你不能使用 @SafeVarargs,但如果你只依赖它的元素类型是 E,那么你可以使用 [=10] =].

在这里,您只迭代 exampleEntities 并从中得到 E。这与 @SafeVarargs.

一致