How can I say that “these two common types are the same” on the map?

I have a toString( Object ) method that delegates the conversion to handlers. Handlers are 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 ); } 

And one 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 problems here:

  • How can I say that the handlers on the specialHandlers map must match the type used as the key?

  • How can I use the same information inside a method to avoid casting and @SuppressWarnings ?

  • When I change the ClassToStringService to implement IToStringService<Class<?>> , I get a compilation error when addSpecialHandler( Class.class, new ClassToStringService() ); How to solve this?

+4
source share
1 answer

You cannot do this in Java. I will explain why.? extends are called existential types in type theory, but Java has a limited form.? continued by X, means that there exists Y such that Y extends X. We can rewrite Map<Class<?>, IToStringService<?>> as:

 Map<Class<(exists T1 extends Object)>, IToStringService<(exist T2 extends Object)>> 

But we want:

 Map<(exists T extends Object Class<T>, IToStringService<T>> 

We cannot express this in Java, because the existence quantifier cannot be explicitly specified in Java. However, in Scala you can do this.

+1
source

Source: https://habr.com/ru/post/1399816/


All Articles