Java 瓦拉格人污染了垃圾堆

Java 瓦拉格人污染了垃圾堆,java,generics,variadic-functions,Java,Generics,Variadic Functions,Java没有文字映射语法,所以我一直在研究初始化文字映射的方法。编译器警告说,参数化vararg类型可能会造成堆污染,这对我来说是新的,所以我读了相关内容。我想我可以用相关的注释来抑制这些警告。但我有两个相关的问题 在这种情况下,是否可以取消警告?(适用于以下代码) 为什么键方法需要两个注释?省略其中任何一个都会使我对“堆污染”警告有所不同,但对我来说两者听起来都一样 你不必批评代码。我只是在玩 这是密码 import java.util.*; public class MapMaker<

Java没有文字映射语法,所以我一直在研究初始化文字映射的方法。编译器警告说,参数化vararg类型可能会造成堆污染,这对我来说是新的,所以我读了相关内容。我想我可以用相关的注释来抑制这些警告。但我有两个相关的问题

  • 在这种情况下,是否可以取消警告?(适用于以下代码)
  • 为什么
    方法需要两个注释?省略其中任何一个都会使我对“堆污染”警告有所不同,但对我来说两者听起来都一样
  • 你不必批评代码。我只是在玩

    这是密码

    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" );
        }
    }
    
    在这种情况下,是否可以取消警告

    在这里,
    Varargs
    被安全地用作:

    • K
      V
      参数类型在编译时限定在实例化
      MapMaker
      时指定的泛型上:

      final Map mapIntStr=new MapMaker()

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

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

    所以是的
    @SafeVarargs
    是有意义的。


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

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

    @SafeVarargs
    @SuppressWarnings("varargs")
    
    不应该是必需的

    @SafeVarargs
    确实足够了,因为
    java.lang.SafeVarargs
    javadoc声明:

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

    您可能应该检查IDE的配置。

    我使用
    javac
    进行测试,仅使用
    @SafeVarargs
    注释不会发出任何警告。

    当我将代码粘贴到IntelliJ中时,如果我删除
    @SafeVarargs
    ,它会抱怨,但是如果我删除
    @SuppressWarnings(“varargs”),则不会从IDE或编译器收到任何警告
    @MikeStrobel:我得到以下信息。我正在使用JavaC1.8.0_152
    MapMaker.java:9:warning:[varargs]varargs方法可能会导致堆污染,因为不可修改的varargs参数键
    您知道java 9中有一个静态工厂方法
    Map.of(key,value,key,value,…)
    ?@DodgyCodeException是,但是我不能在工作中使用Java9,因为我们最近才开始使用Java8。自从1999年我写了第一个Java代码以来,我从来没有使用过最新的版本。我们更糟糕的是:坚持使用Java7。我在家里做Java9只是为了让自己可以工作,我假设这些注释在某种程度上与Java中的通用数组创建问题有关,比如:
    T[]a=(T[])new Object[2]
    -其中T是泛型类型。@davidxxx-如果我删除
    @SuppressWarnings(“varargs”)
    我会得到
    MapMaker.java:9:warning:[varargs]varargs方法可能会导致堆污染,因为不可恢复的varargs参数键
    ,尽管仍然有
    @SafeVarargs
    。我使用的是javac1.8.0_152,所以在1.9?@gil.fernandes中可能已经修复了这一问题。当您执行不安全的强制转换,或者将类型化的内容分配给一个非常广泛的类型作为对象,它可以接受所有内容时,它确实可能会引起问题。优秀资源:@Jonathan我正在使用javac1.8.0_121(比你老),对我来说还可以。你正在使用哪个操作系统?我,Windows。@davidxxx-Windows7,Oracle JDK。我对你的答案很满意,因为这意味着我没有误解某些东西,只是有一个编译器的怪癖。:-)
    @SafeVarargs
    @SuppressWarnings("varargs")