【问题标题】:Runtime casting from String to other datatype从 String 到其他数据类型的运行时转换
【发布时间】:2010-05-17 03:49:30
【问题描述】:

您好,我有字符串值映射。

我想在运行时强制转换这个值。

例如

Map map = new HashMap();
map.put("key1","101");
map.put("key2","45.40");

现在运行时我知道 key1 是 integer 而 key2 是 double 我该如何施放这个。

我试过这个:

("101").getClass().cast(Integer).

////////////////////////////////////// 例如......

String integerClass = "java.lang.Integer"; 字符串 strNum = "5"; 现在如何使用 integerClass 将此 strNum 值“5”转换为 Integer。

.....不直接使用new Integer(strNum)

谢谢。

【问题讨论】:

    标签: java


    【解决方案1】:

    您不能在语言上将 String(引用类型)转换为 intdouble(原始数字类型)。你必须转换它们。值得庆幸的是,有一些标准方法可以为您完成:

    API 链接

    注意

    T Class<T>.cast(Object) 做了完全不同的事情。它与泛型、反射、类型标记等有关。


    也就是说,我注意到您使用了原始的 Map 类型。由于这看起来像一个新代码,应该说您不应该在新代码中使用原始类型。您可能一开始就不需要从 String 转换为 int/double(或者至少在将它们放入地图之前这样做)。

    Map<String,Number>(或者Map<String,Double>)会更好,因为地图是“类型安全的”;你知道它将String 映射到Number,编译器会确保你没有做任何违反这种类型不变量的事情。

    相关问题


    根据 OP 的 cmets,看起来需要这样的东西:

    import java.util.*;
    public class MapTranslate {
        static Object interpret(String s) {
            Scanner sc = new Scanner(s);
            return
                sc.hasNextInt() ? sc.nextInt() :
                sc.hasNextLong() ? sc.nextLong() :
                sc.hasNextDouble() ? sc.nextDouble() :
                sc.hasNext() ? sc.next() :
                s;
        }
        public static void main(String[] args) {
            Map<String,String> map1 = new HashMap<String,String>();
            map1.put("One", "1");
            map1.put("PI", "3.141592653589793");
            map1.put("10^12", "1000000000000");
            map1.put("Infinity", "oo");
            map1.put("Blank", "   ");
    
            Map<String,Object> map2 = new HashMap<String,Object>();
            for (Map.Entry<String,String> entry : map1.entrySet()) {
                map2.put(entry.getKey(), interpret(entry.getValue()));
            }
    
            for (Map.Entry<String,Object> entry: map2.entrySet()) {
                System.out.format("%s->[%s] (%s)%n",
                    entry.getKey(),
                    entry.getValue(),
                    entry.getValue().getClass().getSimpleName()
                );
            }
        }
    }
    

    这会产生:

    PI->[3.141592653589793] (Double)
    Infinity->[oo] (String)
    One->[1] (Integer)
    10^12->[1000000000000] (Long)
    Blank->[   ] (String)
    

    这不是最强大的(例如,它不处理 null 键/值),但它可能是一个很好的起点。请注意,它使用java.util.Scanner 及其hasXXX 方法;这样您就不必担心任何NumberFormatException

    但是,如果不了解大局,就很难评论这样的事情是否是一个好主意。

    相关问题


    使用反射

    这似乎也是问题的一个方面;以下内容应具有指导意义:

    import java.lang.reflect.*;
    
    public class ValueOfString {
        static <T> T valueOf(Class<T> klazz, String arg) {
            Exception cause = null;
            T ret = null;
            try {
                ret = klazz.cast(
                    klazz.getDeclaredMethod("valueOf", String.class)
                    .invoke(null, arg)
                );
            } catch (NoSuchMethodException e) {
                cause = e;
            } catch (IllegalAccessException e) {
                cause = e;
            } catch (InvocationTargetException e) {
                cause = e;
            }
            if (cause == null) {
                return ret;
            } else {
                throw new IllegalArgumentException(cause);
            }
        }
        public static void main(String[] args) throws ClassNotFoundException {
            Integer ii = valueOf(Integer.class, "42"); // no need to cast!
            System.out.println(ii); // prints "42"
    
            Object o = valueOf(Class.forName("java.lang.Double"), "3.14159");
            System.out.println(o);
            System.out.println(o instanceof Double); // prints "true"       
        }
    }
    

    上面的 sn-p 使用类型标记和反射来调用static valueOf(String) 方法。然而,在这种情况下,使用反射可能是不合理的,最好只明确检查所需的转换是什么,例如"java.lang.Integer",然后相应地调用Integer.valueOf

    【讨论】:

    • 我不想转换为任何原始数据类型。
    • @Gengrlin:查看最新版本并告诉我是否有帮助。
    • @Gengrlin:另外,intdouble 是原始数据类型,您最初的问题似乎表明此 conversion 是您想要做的。请说明你的意图;我会尽我所能提供帮助。
    • 谢谢这是最接近的解决方案但是....这是我想要做的......我将参数的数据类型存储在数据库中,并且我从客户端获取字符串中的值所以现在运行时我想将此字符串值转换为所需的数据类型。 ////////////// 示例 .. String integerClass = "java.lang.Integer";字符串 strNum = "5"; ............. 现在,您将如何使用 integerClass 将此 strNum 值“5”转换为 Integer。 .....不直接使用 new Integer(strNum)
    • @Gengrlin:除了java.lang.Integer还有哪些类型?
    【解决方案2】:

    我遇到了类似的问题,并使用 Apache Commons Project 中的 GenericValidator Helper 类解决了它,以找出我认为字符串中可能存在的数据类型,然后对其进行解析。

    public Object parseString(String myString) {
    
            if (GenericValidator.isLong(myString)) {
                return Long.parseLong(myString);
            } else if (GenericValidator.isDouble(myString)) {
                return Double.parseDouble(myString);
            } else if (GenericValidator.isDate(myString, Locale.GERMAN)) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("DD.MM.YYYY");
                return  LocalDate.parse(myString, formatter);
            } else {
                return myString;
            }
    }
    

    https://commons.apache.org/proper/commons-validator/

    【讨论】:

      【解决方案3】:

      你需要把字符串解析成双精度,像这样:

      double d = Double.parseDouble("45.40");
      

      【讨论】:

      • 让我详细解释一下......我的情况是:我在 RunTime::: 有两个地图:第一个地图:key 和 valueClass.......第二个地图:键和值(字符串中的值)....... 现在运行时我想根据需要的第一个映射来转换第二个映射的字符串值 ValueClass 可以是任何数据类型(整数、字符串、双精度、长整数等)
      • 您误用了运行时这个词。我不知道你在问什么。
      【解决方案4】:

      Object 上的 cast 方法将执行 instanceof 测试,并且您可能知道,在这种情况下会抛出 ClassCastException。您可以做的是使用 DoubleInteger 的构造函数,它们接受 String 争论。

      【讨论】:

      • 好的,这是另一个示例。 String integerClass = "java.lang.Integer";字符串 strNum = "5"; ............. 现在,您将如何使用 integerClass 将此 strNum 值“5”转换为 Integer。 .....不直接使用 new Integer(strNum)
      • 那是没用的,因为除非你在编译时知道类型,否则你什么也做不了。
      【解决方案5】:

      您可以使用Integer.parseIntDouble.parseDouble

      int value1 = Integer.parseInt(map.get("key1"));
      double value2 = Double.parseDouble(map.get("key2"));
      

      【讨论】:

      • 没那么简单。它的运行时,所以我得到任何数据类型的类,并且必须根据数据类型接收值进行转换
      【解决方案6】:

      您不能将String转换为任何其他类型,您必须转换它。例如,要转换为Integer

      Integer value = Integer.valueOf(string);
      

      对于Double

      Double value = Double.valueOf(string);
      

      【讨论】:

        【解决方案7】:

        好的,在阅读了额外的 cmets 之后,我想你是这样的:

        static Number convertNumber(String className, String value)
          throws NoSuchMethodException, InvocationTargetException, 
            IllegalArgumentException, IllegalAccessException, ClassNotFoundException {
          Class<?> clazz = Class.forName(className);
          Method method = clazz.getDeclaredMethod("valueOf", String.class);
          return (Number)method.invoke(clazz, value);
        }
        

        你可以这样使用:

        Map<String, String> map1 = new HashMap<String, String>();
        Map<String, String> map2 = new HashMap<String, String>();
        map1.put("key1", "java.lang.Integer");
        map2.put("key1","101");
        map1.put("key2", "java.lang.Double");
        map2.put("key2","45.40");
        
        try {
          Number value;
          value = convertNumber(map1.get("key1"), map2.get("key1"));
          System.out.format("Value = %s, type = %s\n", value, value.getClass().getSimpleName());
          value = convertNumber(map1.get("key2"), map2.get("key2"));
          System.out.format("Value = %s, type = %s\n", value, value.getClass().getSimpleName());
          value = convertNumber("java.lang.Integer", "foo!");
          System.out.format("Value = %s, type = %s\n", value, value.getClass().getSimpleName());
        } catch (Exception e) {
          e.printStackTrace(System.out);
        }
        

        【讨论】:

          【解决方案8】:

          如果我正确理解了您的问题,我认为您可以使用 Java 反射来创建新对象。调用构造函数相当于创建新对象。

          Map&lt;Integer, String&gt; typeMap = new HashMap&lt;Integer, String&gt;();

          Map&lt;Integer, String&gt; valueMap = new HashMap&lt;Integer, String&gt;();

          typeMap.put(1, "java.lang.Double");

          valueMap.put(1, "10");

          Class clazz = Class.forName((String) typeMap.get(1));

          Constructor constructor = clazz.getConstructor(String.class);

          Object obj = constructor.newInstance(valueMap.get(1));

          【讨论】:

            猜你喜欢
            • 2015-09-23
            • 1970-01-01
            • 2011-10-17
            • 1970-01-01
            • 2022-01-02
            • 2013-11-27
            • 2014-06-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多