Java – how can I say “these two generic types are the same” in the map?
I have a method toString (object), which delegates the transformation to the handler The handler is defined as follows:
public interface IToStringService<T> { public String toString( T value ); }
The code is as follows:
// (1) How can I say that these two wildcards must in fact be the same type? private Map<Class<?>,IToStringService<?>> specialHandlers = Maps.newHashMap(); // Generic method,must accept Object (any type really) @Override public String toString( Object value ) { if( null == value ) { return "null"; } Class<?> type = value.getClass(); if( type.isArray() ) { return arrayToString( value ); } // (2) How can I get rid of this SuppressWarnings? @SuppressWarnings( "unchecked" ) IToStringService<Object> handler = (IToStringService<Object>) specialHandlers.get( type ); if( null != handler ) { return handler.toString( value ); } return value.toString(); } public <T> void addSpecialHandler( Class<T> type,IToStringService<T> handler ) { specialHandlers.put( type,handler ); }
An implementation looks like this:
@SuppressWarnings( "rawtypes" ) // Can't add generics to "Class" or I get compile errors when calling DefaultToStringService.addSpecialHandler() :-( public class ClassToStringService implements IToStringService<Class> { @Override public String toString( Class value ) { return value == null ? "null" : value.getName(); } }
I have a few questions:
>How can I say that the handler in the specialhandlers map must match the type used as the key? > How can I use the same information in methods to avoid casts and @ suppresswarnings? > When I change classtostringservice to implement itostringservice < class > When calling addspecialhandler, a compilation error (class. Class, new classtostringservice()) will be encountered; How can I solve this problem?
Solution
You can't do this in Java I'll explain why? Extensions is called existential type in type theory, but Java has a limited form? Extends x means that y exists, so that y extends X. we can rewrite map < class , IToStringService<?>> For example:
Map<Class<(exists T1 extends Object)>,IToStringService<(exist T2 extends Object)>>
But we want to:
Map<(exists T extends Object Class<T>,IToStringService<T>>
We can't express this in Java because we can't explicitly specify the existence quantifier in Java However, you can do this in scala