我试图想出一个让我传入任何对象和默认值的函数,如果对象无法转换为默认值的类型,它应该返回该默认值。如果对象为null,则还应返回默认值。
它应该像这样使用:
Integer myVar = ConversionHelper.initialize( "123", 0 ) // should return Integer(123)
Integer myVar = ConversionHelper.initialize( "hello", 0 ) // should return Integer(0)
等等
我尝试使用以下代码:
public static <T> T initialize(Object o, T def) {
T ret;
try {
ret = (T) o;
} catch (Exception e) {
ret = def;
}
return ret==null ? def : ret;
}
但它失败并进行基本转换,例如将Integer转换为String。
编辑:从答案中得到了许多建议,现在我正在寻找一种方法来做到这一点,而没有if ... elseif ... elseif和我的答案中出现的try catch块系列答案 0 :(得分:3)
这就是你要找的东西:
public static <T> T initialize(Object o, T def) {
if ( o == null ) return def;
if ( def == null ) throw new NullPointerException("Null def");
if ( !def.getClass().isAssignableFrom(o.getClass()) ) {
return def;
} else {
return (T) o;
}
}
但是,正如您在问题中提到的那样,您无法在原始类型上使用它。您需要将它们装入对象才能使用此方法。
修改强>
如果null
是有效选项,则:
public static <T> T initialize(Object o, T def) {
if ( o == null ) return def;
if ( def == null ) null;
if ( !def.getClass().isAssignableFrom(o.getClass()) ) {
return def;
} else {
return (T) o;
}
}
如果检索返回值的属性不能保存null
,则编译器会通过错误告诉您。否则,此代码将会飞行。
答案 1 :(得分:2)
通配符仅作为类型参数有效,而不是类型。在这种情况下,正如您所注意到的那样,普通的旧Object
同样出色。
另一个有效的签名是:
public static <IN, OUT> OUT initialize(IN o, OUT default) { ... }
但是在你的情况下这看起来是不必要的,因为泛型类型是无界的。
至于你在try / catch中使用cast进行转换的策略,我不确定。其他人应该权衡这一部分。
编辑:正如您所发现的那样,除了最简单的数据转换之外,所有内容都非常有限。您可能需要根据in和out类型实现对相应解析方法调用的映射。
EDIT2:作为您所面临的问题的一个示例,这是有人为我正在进行的项目编写的数据转换方法:
public static <T> T mapValueString(String valueString, Class<T> targetType) {
if (valueString == null) {
return null;
}
else if(targetType.equals(String.class)) {
return (T)valueString;
}
else if (targetType.equals(Date.class)) {
return (T)MyDateTime.parseDate(valueString);
}
else if (targetType.equals(Timestamp.class)) {
return (T)MyDateTime.parseTimestamp(valueString);
}
else if (targetType.equals(Boolean.class)) {
String upperVal = valueString.toUpperCase();
if (upperVal.startsWith("T")) {
return (T)Boolean.TRUE;
}
else if (upperVal.startsWith("F")) {
return (T)Boolean.FALSE;
}
else {
throw new RuntimeException("Failed to parse value string into Boolean object. String was " + valueString + ".");
}
}
else if (targetType.equals(Integer.class)) {
Integer i;
try {
i = Integer.parseInt(valueString);
}
catch (NumberFormatException nfe) {
throw new RuntimeException("Failed to parse value string into Integer object. String was " + valueString + ".", nfe);
}
return (T)i;
}
else if (targetType.equals(Long.class)) {
Long l;
try {
l = Long.parseLong(valueString);
}
catch (NumberFormatException nfe) {
throw new RuntimeException("Failed to parse value string into Long object. String was " + valueString + ".", nfe);
}
return (T)l;
}
else if (targetType.equals(Double.class)) {
Double d;
try {
d = Double.parseDouble(valueString);
}
catch (NumberFormatException nfe) {
throw new RuntimeException("Failed to parse value string into Double object. String was " + valueString + ".", nfe);
}
return (T)d;
}
else {
throw new RuntimeException("Unsupported java type " + targetType.getName() + ".");
}
}
请注意,这仅用于将String
映射到T
,您希望将T1
映射到T2
。有没有更好的办法?也许。 SO可以帮助您找到正确的策略吗?当然,但球会在你的球场上提出正确的问题。
EDIT3: Apache Commons' beanutils.converters可能会有所帮助。我没有尝试过,所以我不能评论它。
答案 2 :(得分:2)
public static <T> T initialize(Object o, T def) {
T ret;
try {
ret = def.getClass().cast(o);
} catch (Exception e) {
ret = def;
}
return ret==null ? def : ret;
}
答案 3 :(得分:0)
非常感谢所有答案,但我遇到了以下问题
通过几个基础测试,我很快发现类型的转换能力是有限的(嘿,这里的java新手),我主要考虑将它用于基本类型(数字,字符串,日期,布尔,等)所以我想出了以下
public static <T> T initialize(Object o, T def) {
if (o==null) return def;
try {
if (def.getClass().isAssignableFrom(String.class)) {
return (T) o.toString();
} else if (def.getClass().isAssignableFrom(Integer.class)) {
return (T) Integer.valueOf(o.toString());
} else if (def.getClass().isAssignableFrom(Long.class)) {
return (T) Long.valueOf(o.toString());
} else if (def.getClass().isAssignableFrom(o.getClass())) {
return (T) o;
} else {
return def;
}
} catch (Exception e) {
return def;
}
}
我猜我只需要在路上添加许多其他的东西......
哦,这些是我到目前为止所经历的考验...... assertEquals("trivial case, should return the value passed",
"hello",
initialize("hello", "default salutation"));
assertEquals("should return the default value",
"default salutation",
initialize(null, "default salutation"));
assertEquals("should convert to the default value type",
"123",
initialize(123, "0"));
assertEquals("should convert to the default value type",
(Long) 10L,
initialize("10", 0L));
assertEquals("should return default value if it can't convert to the default value type",
(Long) 0L,
initialize("hola", 0L));
任何更好的选择???