代码之家  ›  专栏  ›  技术社区  ›  Kevin Furlong

类型转换和泛型

  •  0
  • Kevin Furlong  · 技术社区  · 6 年前

    我正在开发一个消息解析库,其中消息体在任何情况下都作为字符串返回。我想创建一个函数,自动将结果转换为正确的类型,但我不确定是否可能。

    我的结构如下: 我有一个名为ReturnType的枚举。它包含返回类型的类变量。

    我有一个函数映射,它将用户试图调用的函数映射为消息响应的返回类型。

    我认为它在某种程度上起到了作用,但问题是我必须将我想要的类包含到getTypedValue()方法调用中,我认为这是多余的,因为我已经知道基于函数映射中ReturnType变量的返回类型。以下是一些代码:

    public enum ReturnType {
        NA(String.class),
        INTEGER(Integer.class),
        JSON(JsonElement.class),
        STRING(String.class),
        FLOAT(Float.class),
        DOUBLE(Double.class),
        IP_ADDRESS(InetAddress.class),
        UNKNOWN(String.class),
        BOOLEAN(Boolean.class);
    
        private Class<?> c;
    
        <T> ReturnType(Class<T> clazz) {
            this.c = clazz;
        }
    
        public Class<?> getClazz() {
            return this.c;
        }
    }
    

    下面是我的getTypedValue()方法:

    public <T> T getTypedValue(String functionName, String value, Class<T> clazz) {
            ReturnType type = this.getReturnType(functionName);
            //TODO: Finish this
            if(type.getClazz().equals(clazz)) {
                switch(type) {
                    case DOUBLE:
                        break;
                    case FLOAT:
                        break;
                    case INTEGER:
                        return clazz.cast(Integer.parseInt(value));
                    case IP_ADDRESS:
                        break;
                    case JSON:
                        break;
                    case STRING:
                        return clazz.cast(value);
                    case UNKNOWN:
                        return clazz.cast(value);
                    default:
                        return clazz.cast(value);
                }
                return null;
            }else {
                throw new UnsupportedOperationException(functionName +" does not support that class("+clazz.getSimpleName()+")");
            }
        }
    

    下面是用户如何调用get-typed值。为了简化,我输入了一个静态值(15),但这实际上是一个从消息响应中获取结果的方法调用:

    Integer volume = fm.getTypedValue("VOLUME", "15", Integer.class);
    

    有没有办法让它返回正确的类型而不提供类?i、 e。

    Integer volume = fm.getTypedValue("VOLUME", "15");
    Double minutes = fm.getTypedValue("MINUTES", "15.25");
    Boolean isRunning = fm.getTypedValue("IS_RUNNING","true");
    

    我不确定这是否可能,即使可能,我目前的代码可能有点难看,难以理解。

    3 回复  |  直到 6 年前
        1
  •  0
  •   Jose Da Silva Gomes Tarsbir Singh    6 年前

    您可以实现这一点,但您将失去编译器提供给您的优势,即在编译时检查类型是否正确。

    使用 getTypedValue 实施类似于:

    @SuppressWarnings({ "unchecked" })
    public <T> T getTypedValue(String functionName, String value) {
        ReturnType type = this.getReturnType(functionName);
        switch(type) {
            case DOUBLE:
            case FLOAT:
            case JSON:
            case IP_ADDRESS:
                break;
            case INTEGER:
                return (T) Integer.valueOf(value);
            case STRING:
            case UNKNOWN:
            default:
                return (T) value;
        }
        return null;
    }
    

    您可以毫无问题地使用它:

    int volume = fm.getTypedValue("VOLUME", "15");
    

    但是,另一方面,您也可以使用它(编译器不会显示任何错误)

    String volume = fm.getTypedValue("VOLUME", "15");
    

    相反,您将收到类型为的运行时异常 ClassCastException 比如说:

    Java语言lang.Integer不能转换为java。lang.字符串


    如果你想要什么 可能 不太容易出错(在编译时而不是运行时显示错误),您可以定义在类中处理/知道/提供的所有函数(枚举不处理泛型)。

    public final class Function<T> {
        private final Class<T> type;
        private Function(Class<T> type) {
            this.type = type;
        }
        public Class<T> getType() {
            return type;
        }
        public static final Function<Integer> VOLUME = new Function<>(Integer.class);
        public static final Function<Boolean> IS_RUNNING = new Function<>(Boolean.class);
        public static final Function<String> NAME = new Function<>(String.class);
    }
    

    ( 您可以根据需要重构,也许可以添加 ReturnType 。您可以在 Function 。还可以在构造函数参数中传递函数的名称,以防以后需要该名称 )

    然后稍微改变一下 getTypedValue 方法:

    public <T> T getTypedValue(Function<T> function, String value) {
        ReturnType returnType = ReturnType.getReturnTypeByClass(function.getType());
        // ... same as before
    }
    

    您可以创建方法 getReturnTypeByClass() 获取 returnType 取决于收到的类别。

    这将起作用:

    int volume = test2.getTypedValue(Function.VOLUME, "123");
    

    这将显示一个编译时错误,非常容易检测和修复:

    String volume = test2.getTypedValue(Function.VOLUME, "123");
    

    最后,您可以将 作用 类和其他类名中函数的声明,例如 Functions

        2
  •  0
  •   Link64    6 年前

    遗憾的是,没有办法。编译器预期该类型在运行时丢失,这将使将其分配给除 Object

    或者,您可以返回 对象 并生成多个 instanceof 支票,但我认为那更糟。

    另一种选择是使用提供的泛型调用该方法。不幸的是,我不确定这是否会导致其他编译错误。尝试以下操作

    Double minutes = fm.<Double>getTypedValue("MINUTES", "15.25");
    

    提供 Class 我在许多不同的库中都见过这样的方法。

        3
  •  0
  •   Chamly Idunil    6 年前

    如下所示修改您的枚举。

    public enum ReturnType {
        NA(String.class) {
            @Override
            public String getValue(String param) {
                return param;
            }
        },
        INTEGER(Integer.class) {
            @Override
            public Integer getValue(String param) {
                return Integer.valueOf(param);
            }
        },
        JSON(JsonElement.class) {
            @Override
            public <T> T getValue(String param) {
                return null;
            }
        },
        STRING(String.class) {
            @Override
            public String getValue(String param) {
                return param;
            }
        },
        FLOAT(Float.class),
        DOUBLE(Double.class),
        IP_ADDRESS(InetAddress.class),
        UNKNOWN(String.class),
        BOOLEAN(Boolean.class);
    
        private Class<?> c;
    
        <T> ReturnType(Class<T> clazz) {
            this.c = clazz;
        }
    
        public Class<?> getClazz() {
            return this.c;
        }
    
        public abstract <T>  T getValue(String param);
    }
    

    您必须在每个ReturnType中实现,以从字符串返回生成的T值。

    然后可以使用ReturnType枚举,如下所示。

    public <T> T getTypedValue(String functionName, String value, Class<T> clazz) {
            ReturnType type = this.getReturnType(functionName);
            if(type.getClazz().equals(clazz)) {
               return type.getValue(value);
            }
            return null;
    }
    

    请善意地忽略编译器错误并修复它。我想给你一个想法,以其他方式实现。