繁体   English   中英

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

[英]Warnings in Java when casting to a generic type

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

我怎样才能摆脱注释?

我有的是:

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);

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

随后的自包含测试程序应该足够清楚:

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));
    ...
    }

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

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);

您可以以相同的方式使第二个强制转换安全,或者(假设您只是读取不修改它的映射)按原样使用映射(使用通配符参数)并将值转换为每个查找的字符串:

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

或包裹地图:

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

// ...

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

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

例如。

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

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

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

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

SharedContext<Object>

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM