Varargs污染堆

时间:2018-01-08 15:45:07

标签: java generics variadic-functions

Java没有文字地图语法,因此我正在尝试初始化地图文字的方法。编译器警告Possible heap pollution from parameterized vararg type这对我来说是新的,所以我读到了这一点。我认为我可以通过相关注释来抑制这些警告。但我有两个相关的问题。

  1. 我是对的,在这种情况下可以抑制警告吗? (对于下面的代码)
  2. 为什么我需要keys方法的两个注释?忽略其中任何一个都会让我对“堆污染”警告做出改变,但两者对我来说都是一样的。
  3. 您不必批评代码。我只是在玩。

    这是代码。

    import java.util.*;
    
    public class MapMaker<K, V>{
        private K [] m_keys;
    
        @SafeVarargs
        @SuppressWarnings("varargs")
        public final MapMaker<K, V> keys( final K... keys ){
            m_keys = keys;
            return this;
        }
    
        @SafeVarargs
        public final Map<K, V> values( final V... values ){
            if ( values.length != m_keys.length )
                throw new IllegalArgumentException( "Mismatch - keys: " + m_keys.length + ", values " + values.length );
    
            final Map<K, V> result = new HashMap<>();
    
            for ( int i = 0; i < m_keys.length; i++ )
                result.put( m_keys[ i ], values[ i ] );
    
            return result;
        }
    
        public static void main( String [] args ){
            final Map<Integer, String> mapIntStr = new MapMaker<Integer, String>()
                    .keys  ( 1,     2,     3       )
                    .values( "One", "Two", "Three" );
    
            System.out.println( mapIntStr );
    
            final Map<String, String> mapStrStr = new MapMaker<String, String>()
                    .keys  ( "1" )
                    .values( "One", "Two" );
        }
    }
    

    输出

    {1=One, 2=Two, 3=Three}
    Exception in thread "main" java.lang.IllegalArgumentException: Mismatch - keys: 1, values 2
        at MapMaker.values(MapMaker.java:16)
        at MapMaker.main(MapMaker.java:35)
    

1 个答案:

答案 0 :(得分:1)

  

我是对的,在这种情况下可以抑制警告吗?

此处Varargs安全地用作:

  • KV参数类型在编译时限制为您实例化MapMaker时指定的泛型:

    final Map<Integer, String> mapIntStr = new MapMaker<Integer, String>()

  • 您不会使用vargs变量执行不安全的强制转换,也不会将它们分配给声明的Object[]数组,以使用可能导致java.lang.ArrayStoreException的不兼容对象对其进行评估(即不是堆污染,但这也是有问题的。)

  • 您使用泛型数组而不是泛型集合数组。堆配置污染在此配置中不太常见,因为您没有可能包含可能触发ClassCastException的不兼容元素的集合。

所以是的@SafeVarargs是有道理的。

  

为什么我需要为keys方法添加两个注释?

使用以下两种方法注释keys()方法:

@SafeVarargs
@SuppressWarnings("varargs")

不应该被要求。

@SafeVarargs确实足够java.lang.SafeVarargs javadoc状态:

  

将此注释应用于方法或构造函数抑制   关于不可恢复的变量arity(vararg)类型的未经检查的警告   并禁止有关参数化数组创建的未经检查的警告   在呼叫站点。

你应该检查你的IDE配置。
我使用javac进行了测试,并且仅使用@SafeVarargs注释不会发出警告。