我怎么能在地图中说“这两种通用类型是一样的”?

时间:2012-03-05 15:40:35

标签: java generics

我有一个方法toString( Object ),它将转换委托给处理程序。处理程序的定义如下:

public interface IToStringService<T> {
    public String toString( T value );
}

代码如下所示:

// (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 );
}

一个实现看起来像这样:

@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();
    }
}

我有几个问题:

  1. 如何说specialHandlers地图中的处理程序必须与用作密钥的类型相匹配?

  2. 如何在方法中使用相同的信息以避免转换和@SuppressWarnings

  3. 当我更改ClassToStringService以实现IToStringService<Class<?>>时,我在调用addSpecialHandler( Class.class, new ClassToStringService() );时遇到编译错误如何解决此问题?

1 个答案:

答案 0 :(得分:1)

你不能用Java做到这一点。我会解释原因。 ? extends在类型理论中称为存在类型,但Java具有有限的形式。 ? extends X表示存在Y,Y表示X.我们可以将Map<Class<?>, IToStringService<?>>重写为:

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

但我们想:

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

我们无法在Java中表达这一点,因为不能在Java中明确指定存在量词。但是,在Scala中你可以这样做。