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