8

我想创建一个有效地做到这一点的通用方法:

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子类,并为子类返回 0 值Number

4

5 回答 5

3

Java 泛型仅提供编译时检查,并且类型信息在编译后几乎被丢弃。因此,该语句T.valueOf在 Java 中是不可能的。解决方案是采用评论中已经提到的详细方式。此外,您是否有任何理由想要这样做,MyClass.<Double>sloppyParseNumber(value)但不是MyClass.sloppyParseDouble(value)因为您在编译时指定了类型?

于 2013-04-16T06:41:14.080 回答
3

我 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,您无法在运行时获取类型。

于 2013-04-16T06:55:41.433 回答
2

静态方法受类型的约束,因为类型充其量是没有方法的,您所追求的Number方法是行不通的。NumbervalueOf

最简单的方法是制作一些静态方法,如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;
        }    
    }
}
于 2013-04-16T06:46:19.223 回答
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". 完全做到这一点需要两种不同的方法,一种支持小数点,另一种只支持整数。

于 2013-04-16T07:16:37.670 回答
0

你可以试试这个:

private <T> T convertToType(Class<T> clazz,String str) throws Exception {
    return clazz.getConstructor(String.class).newInstance(str);
}

这里需要考虑Type必须有一个带String参数的构造函数。

于 2016-04-22T23:04:48.397 回答