Приведение во время выполнения из String к другому типу данных - PullRequest
5 голосов
/ 17 мая 2010

Привет, у меня есть карта значений String.

Я хочу привести это значение во время выполнения.

, например

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

Теперь я знаю, что во время выполнения key1 является целым числом, а key2 - двойным Как я могу разыграть это?

Я пробовал это:

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

////////////////////////////////////////////// например ...........

String integerClass = "java.lang.Integer"; String strNum = "5"; Теперь, как вы будете преобразовывать это значение strNum "5" в Integer, используя integerClass.

..... Без использования нового Integer (strNum) напрямую

Спасибо.

Ответы [ 8 ]

8 голосов
/ 17 мая 2010

Вы не можете лингвистически привести String (ссылочный тип) к int или double (примитивный числовой тип). Вы должны конвертировать их. К счастью, есть стандартные способы сделать их для вас:

API ссылки

Примечание

T Class<T>.cast(Object) делает что-то совершенно другое. Это имеет отношение к дженерикам, рефлексии, тип-токенам и т. Д.


Тем не менее, я заметил, что вы использовали необработанный тип Map. Поскольку это выглядит как новый код, следует сказать, что вы НЕ должны использовать необработанные типы в новом коде. Вполне возможно, что вам никогда не понадобится конвертировать из String в int / double в первую очередь (или, по крайней мере, сделать это ДО , когда вы поместите их в карту).

A Map<String,Number> (или, возможно, Map<String,Double>) будет лучше, потому что карта является "безопасной для типов"; вы знаете, что он сопоставляет String с Number, и компилятор гарантирует, что вы ничего не делаете для нарушения этого инварианта типа.

Смежные вопросы


Судя по комментариям ОП, выглядит примерно так:

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"       
    }
}

Приведенный выше фрагмент использует токены типа и отражения для вызова метода static valueOf(String). Однако использование отражения может быть неоправданным в этом случае, и может быть просто лучше просто явно проверить, что представляет собой желаемое преобразование, например, "java.lang.Integer", а затем вызвать Integer.valueOf соответственно.

2 голосов
/ 13 ноября 2015

У меня была похожая проблема, и я решил ее, используя вспомогательный класс GenericValidator из проекта Apache Commons, чтобы выяснить, какой тип данных, как я предполагаю, мог быть в строке, а затем проанализировать его.

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/

1 голос
/ 17 мая 2010

Вам нужно разобрать строку в двойное число, например:

double d = Double.parseDouble("45.40");
0 голосов
/ 17 мая 2010

Если я правильно понял вашу проблему, думаю, вы могли бы использовать Java Reflection для создания новых объектов. Вызов конструктора эквивалентен созданию новых объектов.

Map<Integer, String> typeMap = new HashMap<Integer, String>();

Map<Integer, String> valueMap = new HashMap<Integer, String>();

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));

0 голосов
/ 17 мая 2010

ОК, после прочтения дополнительных комментариев, я думаю, что вы после чего-то вроде этого:

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);
}
0 голосов
/ 17 мая 2010

Вы не можете кастовать a String в любой другой тип, вы должны конвертировать это. Например, для преобразования в Integer:

Integer value = Integer.valueOf(string);

Для Double:

Double value = Double.valueOf(string);
0 голосов
/ 17 мая 2010

Вы можете использовать Integer.parseInt и Double.parseDouble

int value1 = Integer.parseInt(map.get("key1"));
double value2 = Double.parseDouble(map.get("key2"));
0 голосов
/ 17 мая 2010

метод cast на Object выполнит тест instanceof, и, как вы, вероятно, знаете, в этом случае выдаст ClassCastException. Что вы можете сделать, так это использовать конструкторы для Double и Integer, которые принимают String аргументов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...