[英]Java generics and numeric types
我想创建一个有效的通用方法:
class MyClass {
static <T extends Number> T sloppyParseNumber(String str) {
try {
return T.valueOf(str);
} catch (Exception e) {
return (T)0;
}
}
}
现在上面没有编译有两个原因:没有Number.valueOf()
方法,0不能转换为T
用法示例:
String value = "0.00000001";
System.out.println("Double: " + MyClass.<Double>sloppyParseNumber(value));
System.out.println("Float: " + MyClass.<Float>sloppyParseNumber(value));
double d = MyClass.sloppyParseNumber(value);
float f = MyClass.sloppyParseNumber(value);
用Java实现上面的通用方法吗? 如果有,怎么样? 如果不是,那么什么是一个好的替代方法?
编辑:似乎有一些可能的重复,但我没有找到一个,这涵盖了这一点。 我希望有一些技巧可以提取,这将允许这两个操作:将字符串解析为Number
子类,并为Number
子类返回0值。
Java泛型只提供编译时检查,编译后几乎丢弃了类型信息。 所以语句T.valueOf
在Java中是不可能的。 解决方案是采用评论中已经提到的冗长方式。 另外,你有什么理由要做MyClass.<Double>sloppyParseNumber(value)
但不是MyClass.sloppyParseDouble(value)
因为你无论如何在编译时指定类型?
我同意100%与TofuBeer。 但是如果您希望为了时间而避免冗长,这也应该:
static <T extends Number> T sloppyParseNumber(String str,Class<T> clas) {
if (clas == null) throw new NullPointerException("clas is null");
try {
if(clas.equals(Integer.class)) {
return (T) Integer.valueOf(str);
}
else if(clas.equals(Double.class)) {
return (T) Double.valueOf(str);
}
//so on
catch(NumberFormatException|NullPointerException ex) {
// force call with valid arguments
return sloppyParseNumber("0", clas);
}
throw new IllegalArgumentException("Invalid clas " + clas);
}
但纯粹来自T
,你无法在运行时获得类型。
静态方法受类型的约束,因为类型最多只有Number
和Number
没有valueOf
方法,所以你不能使用它。
最简单的方法是制作一些静态方法,如sloppyParseInt
, sloppyParseFloat
等...
你可以做这样的事情,不确定我喜欢它,并且可以改进:
public class Main
{
private static final Map<Class<? extends Number>, NumberConverter> CONVERTERS;
static
{
CONVERTERS = new HashMap<>();
CONVERTERS.put(Integer.class, new IntegerConverter());
}
public static void main(String[] args)
{
Number valueA;
Number valueB;
valueA = CONVERTERS.get(Integer.class).convert("42");
valueB = CONVERTERS.get(Integer.class).convert("Hello, World!");
System.out.println(valueA);
System.out.println(valueB);
}
}
interface NumberConverter<T extends Number>
{
T convert(String str);
}
class IntegerConverter
implements NumberConverter<Integer>
{
@Override
public Integer convert(String str)
{
try
{
return Integer.valueOf(str);
}
catch (NumberFormatException ex)
{
return 0;
}
}
}
所以,我决定采用另一种方法:
static String trimTo0(String str) {
if (str == null) return "0";
str = str.trim();
if (str.isEmpty()) return "0";
return str;
}
用法:
String value = null;
System.out println("Double value: " + Double.parseDouble(trimTo0(value)));
请注意,这比问题中的方法更有限,这不会将无效的非数字字符串转换为"0"
。 完全这样做需要两个单独的方法,一个支持小数点,另一个支持整数。
你可以试试这个:
private <T> T convertToType(Class<T> clazz,String str) throws Exception {
return clazz.getConstructor(String.class).newInstance(str);
}
在这里,您需要考虑Type必须具有带String参数的构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.