Java warnings when passing to a generic type

I have a common code that I cannot figure out how to legally prevent the receipt of warnings; I am using @SuppressWarnings ("unchecked") at the moment, as it seems that generic type casting cannot be performed without warnings.

How can I get rid of the annotation?

I have:

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

The context of the protected variable is the type SharedContext<Object> .

Without annotation, the compiler generates warnings:

 ...\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); 
+7
java generics warnings
source share
5 answers

After some further research, I believe that I have found a reasonable alternative that at least limits the annotation of suppression to only one global static utility method to make an unchecked listing.

The independent test program that follows should be fairly clear:

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

Another blog post suggests improving this utility method:

 @SuppressWarnings("unchecked") public static <T, X extends T> X uncheckedCast(T o) { return (X) o; } 

forcing what is returned by a subclass of the passed parameter.

Assuming I put uncheckedCast in a public GenUtil class, my launch method in the question will not have any (useless) warnings that go out and look like this:

 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)); ... } 
+4
source share

Is the SharedContext object what you wrote? If so, is it possible to replace the general String-> Object mapping with specific fields?

eg.

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

The general hold-all context object always seems to me a less than ideal solution. This is especially true for generics and unverified cast messages.

Alternatively, you can create a wrapper object named SoftwareMonkeyContext that has certain setter / getter methods, as described above, and uses your GenUtil.uncheckedCast method internally. This may prevent you from using GenUtil.uncheckedCast in several places in your code.

+1
source share

The first unchecked listing can be eliminated by defining a non-generic class that extends the generic Map<String, Pair<String, Boolean>> and stores it in a SharedContext instead of a generic TreeMap , for example. (using ForwardingMap from 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); 

You can make the second throw mode the same way (or if you are only reading the map without changing it) use the map as is (with wildcard parameters) and convert the value to a string with each search:

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

or wrap the card:

 Map<?, String> wrappedOutputFields = Maps.transformValues(outputFields, Functions.toStringFunction()); // ... String bar = wrappedOutputFields.get("foo"); 
+1
source share

How is the context variable assigned? This is from the ctx parameter, which is of type:

 SharedContext<Object> 

?

If so, this is your problem, because when you do this, you do not score what you get.

0
source share

What version of compiler are you using? With the Java compiler (Sun JDK windows), I did not see a detailed warning. I only get warning information when I use the "-Xlint: unchecked" flag.

Try -Xlint: -disconnected and let us know if it solves your problem. More on flags

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

0
source share

All Articles