在转换为泛型类型时,Java中的警告

时间:2010-02-20 04:27:41

标签: java generics warnings

我有一些通用代码,我无法弄清楚如何合法地阻止警告;我目前正在使用@SuppressWarnings(“未经检查”),因为似乎在没有警告的情况下无法完成转换泛型类型。

如何摆脱注释?

我拥有的是:

public MyObject(SharedContext<Object> ctx) {
    super(ctx); // set protected field 'context'
    ...
    context.set("Input Fields"  ,Collections.synchronizedMap(new TreeMap<String,Pair<String,Boolean>>(String.CASE_INSENSITIVE_ORDER)));
    context.set("Output Fields" ,Collections.synchronizedMap(new TreeMap<String,String>              (String.CASE_INSENSITIVE_ORDER)));
    context.set("Event Registry",new EventRegistry(log)                                                                              );
    }

@SuppressWarnings("unchecked")
protected void startup() {
    inputFields     =(Map<String,Pair<String,Boolean>>)context.get("Input Fields"  ,null);
    outputFields    =(Map<String,String>              )context.get("Output Fields" ,null);
    eventRegistry   =(EventRegistry                   )context.get("Event Registry",null);
    ...
    }

受保护的变量上下文是SharedContext<Object>类型。

如果没有注释,编译器会发出警告:

...\MyClass.java:94: warning: [unchecked] unchecked cast
found   : java.lang.Object
required: java.util.Map<java.lang.String,com.mycompany.Pair<java.lang.String,java.lang.Boolean>>
    inputFields     =(Map<String,Pair<String,Boolean>>)context.get("Input Fields"  ,null);
                                                                  ^
...\MyClass.java:95: warning: [unchecked] unchecked cast
found   : java.lang.Object
required: java.util.Map<java.lang.String,java.lang.String>
    outputFields    =(Map<String,String>              )context.get("Output Fields" ,null);

5 个答案:

答案 0 :(得分:3)

经过一些进一步的研究后,我相信我找到了一个合理的替代方案,它至少将抑制注释限制为一个全局静态实用方法来进行未经检查的转换。

下面的自包含测试程序应该足够清楚:

public class Generics
{

static public void main(String[] args) {
    Generics.test();
    }

static private void test() {
    Map<String,Object> ctx=new TreeMap<String,Object>();
    Map<String,Object> map=new TreeMap<String,Object>();
    Map<String,Object> tst;

    ctx.put("Test",map);
    tst=uncheckedCast(ctx.get("Test"));
    }

@SuppressWarnings({"unchecked"})
static public <T> T uncheckedCast(Object obj) {
    return (T)obj;
    }

}

另一篇博客建议对此实用程序方法进行改进:

@SuppressWarnings("unchecked") 
public static <T, X extends T> 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));
    ...
    }

答案 1 :(得分:2)

可以通过定义扩展通用Map<String, Pair<String, Boolean>>并将其存储在SharedContext而不是通用TreeMap中的非泛型类来消除第一个未经检查的强制转换。 (使用ForwardingMap中的Guava):

class InputFieldMap extends ForwardingMap<String,Pair<String,Boolean>> {

    private final Map<String,Pair<String,Boolean>> delegate =
        Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
    protected Map<String,Pair<String,Boolean>> 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);

您可以以相同的方式使第二个演员安全,或者(假设您只是阅读地图而不修改它)按原样使用地图(使用通配符参数)并将值转换为每个查找的字符串:< / p>

String bar = String.valueOf(outputFields.get("foo"));

或包裹地图:

Map<?, String> wrappedOutputFields    =
    Maps.transformValues(outputFields, Functions.toStringFunction());

// ...

String bar = wrappedOutputFields.get("foo");

答案 2 :(得分:1)

您写的SharedContext对象是一个吗?如果是这样,是否可以用特定字段替换通用String-&gt; Object映射?

例如

context.setInputFields(...)
context.setOutputFields(...)
context.setEventRegistry(...)
context.getInputFields()
etc.

通用hold-all上下文对象对我来说似乎总是不太完美。特别是使用泛型和未经检查的强制转换消息。

或者,您可以创建一个名为SoftwareMonkeyContext的包装器对象,该对象具有上述特定的setter / getter方法,并在内部使用您的GenUtil.uncheckedCast方法。这样可以防止您需要在代码中的多个位置使用GenUtil.uncheckedCast。

答案 3 :(得分:0)

如何分配context变量?它来自参数ctx,它的类型为:

SharedContext<Object>

如果是这样,那就是你的问题,因为当你这样做时,你没有有效地输入你得到的东西。

答案 4 :(得分:0)

您使用的是哪个版本的编译器?使用Java 6编译器(Sun JDK windows),我没有看到详细的警告。我只在使用'-Xlint:unchecked'标志时才收到警告信息。

尝试-Xlint:-unchecked并告诉我们它是否可以解决您的问题。有关标志的更多信息,

http://java.sun.com/javase/6/docs/technotes/tools/windows/javac.html