我下面的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
}


它引发以下警告:


  类型安全性:通过varargs参数示例产生的潜在堆污染


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

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

此方法类似于java.util.Collections.addAll中提到的方法the Java Specification §9.6.3.7,该方法用@SafeVarargs注释。
This 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,则可以使用@SafeVarargs

在这里,您仅遍历exampleEntities并从中获取E。这与@SafeVarargs一致。

07-28 13:19