简体   繁体   中英

How to determine type in a generic method in Java?

I want a method that extracts the data from a JSON-object parsed before as the correct type. The JSONObject (rawdata) extends Map, so it looks like this:

private <Type> Type getValue(String key, Type def)
{
    if (!rawdata.containsKey(key)) return def;
    if (!(rawdata.get(key) instanceof Type)) return def;
    return (Type) rawdata.get(key);
}

The instanceof obviously generates a compile-time-error. The parameter def is the default-value, returned if the key is not available or has the wrong type. But def can also be null, so def.getClass() isn't working.

Any ideas how I can check the content of the Map-entry for the correct type?

由于类型擦除,处理默认值可以为null的情况的唯一方法是让该方法需要一个额外的Class类型的参数-通常更好,因为它允许默认值成为所需类型的子类。

You just need to check for nulls (a null will count as any type, if this is undesired behaviour then you will also need to pass in the desired class).

private <T> T getValue(String key, T def)
{
    if (!rawdata.containsKey(key)) return def;

    Object value = rawdata.get(key);

    if (def == null) return (T) value; 
    // note that the above is inherently unsafe as we cannot 
    // guarantee that value is of type T

    // this if statement is the same as "value instanceOf Type"
    // is type safe, but not null safe
    if (def.getClass().isAssignableFrom(value.getClass())) {
        return (T) value;
    } else {
        return def;
    }
}

A safer method signature would be:

private <T> T getValue(String key, T defaultValue, Class<T> defaultClass)

This way we can safely check the types match even when the default is null.

Your best bet is probably to accept a Class object for the return type in the case when no default value is given. You can just overload the function like:

private <T> T getValue(String key, Type defaultValue);

private <T> T getValue(String key, Class<T> type);

Or you could use the Typesafe Heterogeneous Container (THC) pattern from "Effective Java Second Edition" book by Joshua Bloch.

Basically, store the item's Class in the map when inserting. When retrieving you'll know the type is the same.

Map<Class, Map<String, Object>> rawData = ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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