Java泛型和数值类型
我想创建一个通用方法,它可以有效地执行以下操作:Java泛型和数值类型,java,generics,Java,Generics,我想创建一个通用方法,它可以有效地执行以下操作: class MyClass { static <T extends Number> T sloppyParseNumber(String str) { try { return T.valueOf(str); } catch (Exception e) { return (T)0; } } } 用Java实现上述通用方法
class MyClass {
static <T extends Number> T sloppyParseNumber(String str) {
try {
return T.valueOf(str);
} catch (Exception e) {
return (T)0;
}
}
}
用Java实现上述通用方法可行吗?如果是,如何进行?如果没有,什么是好的替代方法
编辑:似乎有一些可能的重复,但我没有找到一个,这正好涵盖了这一点。我希望有一些技巧可以使用,这将允许这两个操作:将字符串解析为
Number
子类,并为Number
子类返回0值。Java泛型只提供编译时检查,编译后类型信息几乎被丢弃。因此,Java中不可能使用T.valueOf
语句。解决方案是按照评论中已经提到的详细方式进行。还有,既然您在编译时指定了类型,那么您为什么要执行MyClass.sloppyParseNumber(value)
,而不执行MyClass.sloppyParseDouble(value)
,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;
}
}
}
公共类主
{
私有静态最终地图我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);
}
static T sloppyParseNumber(字符串str,类clas){
如果(clas==null)抛出新的NullPointerException(“clas为null”);
试一试{
if(类等于(整数类)){
返回(T)整数。值为(str);
}
else if(类等于(双类)){
返回值(T)加倍。值(str);
}
//诸如此类
catch(NumberFormatException | NullPointerException ex){
//带有效参数的强制调用
返回sloppyParseNumber(“0”,clas);
}
抛出新的IllegalArgumentException(“无效clas”+clas);
}
但是纯粹从T
,您无法在运行时获取类型。因此,我决定采用另一种方法:
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);
}
private T convertToType(类clazz,字符串str)引发异常{
返回clazz.getConstructor(String.class).newInstance(str);
}
这里,您需要考虑的是,该类型必须具有一个字符串参数的构造函数。
抽象类不包含任何将字符串解析为一个类型的方法,因为解析是由特定类型完成的。建议不要使用泛型,而是创建函数如<代码>…to整型< /COD>,<代码>……双/<代码>等等。我不认为有一个简单的方法可以做到这一点。我只需要使用像newmyclass(value).asDouble();
这样的东西,并实现asInteger
,asLong
,asFloat
,asDouble
等。手动方法t.valueOf()
即使有一个静态方法Number.valueOf(),也不起作用
;您不能像这样使用泛型类型。这可能是的重复。我认为更好的API应该是调用NumberConvert.convert(Integer.class,string)
,并在内部处理细节。@hyde:我不确定我是否理解。当您说“它的功能与往常一样,指定类型不起任何作用",为什么您认为指定类型没有任何作用?在您更新的示例中,slopyParseNumber
的返回类型是什么?它如何知道传入的数字是否应该被解析为BigDecimal
,Double
,Float
,Integer
等?让我们再试一次:MyClass.slopp的目的yParseNumber将使方法返回双对象,但实际上Java泛型并不是这样工作的,方法无法知道调用方在
中指定的类型。这似乎是最接近我在问题中提出的方法,尽管我仍然希望您的答案包括捕获异常并返回e right子类(因此返回T
并具有类clas
参数,我猜)。
private <T> T convertToType(Class<T> clazz,String str) throws Exception {
return clazz.getConstructor(String.class).newInstance(str);
}