在转换为generics类型时,Java中的警告
我有一些通用代码,我无法弄清楚如何合法地阻止警告; 我目前正在使用@SuppressWarnings(“未经检查”),因为似乎在没有警告的情况下无法完成转换generics类型。
我怎样才能摆脱注释?
我所拥有的是:
public MyObject(SharedContext ctx) { super(ctx); // set protected field 'context' ... context.set("Input Fields" ,Collections.synchronizedMap(new TreeMap<String,Pair>(String.CASE_INSENSITIVE_ORDER))); context.set("Output Fields" ,Collections.synchronizedMap(new TreeMap (String.CASE_INSENSITIVE_ORDER))); context.set("Event Registry",new EventRegistry(log) ); } @SuppressWarnings("unchecked") protected void startup() { inputFields =(Map<String,Pair>)context.get("Input Fields" ,null); outputFields =(Map )context.get("Output Fields" ,null); eventRegistry =(EventRegistry )context.get("Event Registry",null); ... }
受保护的变量上下文是SharedContext
类型。
如果没有注释,编译器会发出警告:
...\MyClass.java:94: warning: [unchecked] unchecked cast found : java.lang.Object required: java.util.Map<java.lang.String,com.mycompany.Pair> inputFields =(Map<String,Pair>)context.get("Input Fields" ,null); ^ ...\MyClass.java:95: warning: [unchecked] unchecked cast found : java.lang.Object required: java.util.Map outputFields =(Map )context.get("Output Fields" ,null);
经过一些进一步的研究后,我相信我找到了一个合理的替代方案,它至少将抑制注释限制为一个全局静态实用方法来进行未经检查的转换。
随后的自包含测试程序应该足够清楚:
public class Generics { static public void main(String[] args) { Generics.test(); } static private void test() { Map ctx=new TreeMap(); Map map=new TreeMap(); Map tst; ctx.put("Test",map); tst=uncheckedCast(ctx.get("Test")); } @SuppressWarnings({"unchecked"}) static public T uncheckedCast(Object obj) { return (T)obj; } }
另一篇博客建议改进这种实用方法:
@SuppressWarnings("unchecked") public static X uncheckedCast(T o) { return (X) o; }
强制返回的内容是传入的参数的子类。
假设我将uncheckedCast放入公共实用程序类GenUtil中,我在问题中的启动方法将没有(无用的)警告发出,看起来像:
protected void startup() { inputFields =GenUtil.uncheckedCast(context.get("Input Fields" ,null)); outputFields =GenUtil.uncheckedCast(context.get("Output Fields" ,null)); eventRegistry=GenUtil.uncheckedCast(context.get("Event Registry",null)); ... }
SharedContext对象是您编写的对象吗? 如果是这样,是否可以用特定字段替换通用String-> Object映射?
例如。
context.setInputFields(...) context.setOutputFields(...) context.setEventRegistry(...) context.getInputFields() etc.
对我来说,通用的hold-all上下文对象似乎总是不太完美。 特别是使用generics和未经检查的强制转换消息。
或者,您可以创建一个名为SoftwareMonkeyContext的包装器对象,该对象具有上述特定的setter / getter方法,并在内部使用您的GenUtil.uncheckedCast方法。 这可以防止您需要在代码中的多个位置使用GenUtil.uncheckedCast。
可以通过定义扩展genericsMap
并将其存储在SharedContext
而不是通用TreeMap
的非generics类来消除第一个未经检查的强制转换,例如(使用来自Guava的 ForwardingMap ):
class InputFieldMap extends ForwardingMap> { private final Map> delegate = Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER); protected Map> delegate() { return delegate; } } // ... context.set("Input Fields" ,Collections.synchronizedMap(new InputFieldMap())); // ... inputFields =(InputFieldMap)context.get("Input Fields" ,null); outputFields =(Map,?> )context.get("Output Fields" ,null);
您可以以相同的方式使第二个强制转换安全,或者(假设您只是读取地图而不修改它)使用映射(使用通配符参数)并将值转换为每个查找的字符串:
String bar = String.valueOf(outputFields.get("foo"));
或包裹地图:
Map, String> wrappedOutputFields = Maps.transformValues(outputFields, Functions.toStringFunction()); // ... String bar = wrappedOutputFields.get("foo");
如何分配context
变量? 它来自参数ctx,它的类型是:
SharedContext
?
如果是这样,那就是你的问题,因为当你做了一个让你没有有效输入你得到的东西。
您使用的是哪个版本的编译器? 使用Java 6编译器(Sun JDK windows),我没有看到详细的警告。 我只在使用’-Xlint:unchecked’标志时才收到警告信息。
尝试-Xlint:-unchecked并告诉我们它是否可以解决您的问题。 有关旗帜的更多信息,
http://java.sun.com/javase/6/docs/technotes/tools/windows/javac.html