>我构建了一个简单的文档存储,有些实体具有不同类型的字段,我有浮点型、Int 型和字符串型。该实体包含一个值的数组列表,如果有人更新实体的架构,我希望能够尝试将值转换为新类型。
public interface FieldType<T> {
ArrayList<T> values;
}
public class FloatField implements FieldType<Float> {
}
public class StringField implements FieldType<String> {
}
我考虑过使用带有以下方法的抽象类
public abstract class Field<T> implements FieldType<T> {
abstract public <T> castFromString(String value);
abstract public <T> castFromFloat(Float value);
abstract public <T> castFromInt(Int value);
}
public class FloatField extends Field<Float> {
@override
public <Float> castFromString(String value){
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
}
return castValue;
}
}
我不太喜欢这个解决方案,因为每次向系统添加额外的类型时,我都必须添加新的抽象方法。
有什么想法可以更好地实现这一点吗?
也许您可以使用Function<T, R>
界面?
public abstract class Field<T> implements FieldType<T> {
...
public <F> T convert(F value, Function<F, T> converter) {
try {
return converter.apply(value);
} catch(Exception e) {
return null;
}
}
...
}
然后使用 lambda 表达式或方法引用指定转换器:
field.convert("1234", BigDecimal::new); //with a method reference
field.convert("1234", s -> new BigDecimal(s)) //with a lambda
这会将所有convertXXX
方法替换为一个,因为返回类型是从传递的Function
推断出来的。
编辑:如果要自动转换,当然必须对这些进行硬编码,因为您不想在 Java API 中为所有 4240 类编写转换方法。不过,这变得很混乱。也许在静态帮助程序类或FieldType
本身中类似的东西?
public class WhereverYouWantThis {
private static HashMap<Class<?>, HashMap<Class<?>, Function<?, ?>>> converters = new HashMap<>();
static {
putConverter(String.class, Float.class, Float::parseFloat);
}
private static <T, R> void putConverter(Class<T> t, Class<R> r, Function<T, R> func) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) converters.put(t, map = new HashMap<>());
map.put(r, func);
}
public static <T, R> Function<T, R> getConverter(Class<T> t, Class<R> r) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) return null;
@SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) map.get(r);
return func;
}
public static <T, R> R convert(T o, Class<R> to) {
@SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) getConverter(o.getClass(), to);
return func == null ? null : func.apply(o);
}
}
<</div>
div class="one_answers">我认为您不需要泛型。 相反,只需尝试从输入String
创建一个Float
,并在出现问题时返回null
:
public Float castFromString(String value) {
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
// log here
}
return castValue;
}
我认为不需要泛型的原因是转换中涉及的类型在您的帮助程序方法中是命名/已知的。