Динамическое приведение к примитивам в Java

Изменить: с тех пор это было решено. Спасибо всем, кто помог. Вызов метода после приведения объекта как правильный класс обертки сработал. Но String.valueOf() намного, намного проще достичь того же эффекта.

Привет--

То, что я пытаюсь сделать, может даже оказаться невозможным. Я провел несколько часов, исследуя и экспериментируя с различными вещами, поэтому я решил наконец спросить, не знает ли кто-нибудь, возможно ли это.

Можно ли с помощью отражения динамически приводить оболочку для примитива неизвестного типа в качестве примитива?

Я в основном пытаюсь создать универсальную функцию toString, которая может обрабатывать преобразование любого типа примитива в строку. Такая на первый взгляд простая вещь разочаровывающе трудна (и я знаю, что могу просто протестировать каждый тип, чтобы увидеть, относится ли он к типу Wrapper.class, и специально разыграть его, но на данный момент я просто преследую это из упрямства).

Следующее создает исключение ClassCastException. Класс primClass выглядит правильным (дает "int" при печати primClass.getName()).

    private String toString(Number obj){
    String result = "";
    try{
        Class objClass = obj.getClass();
        Field field = objClass.getDeclaredField("TYPE");
        Class primClass = (Class)field.get(obj);
        Method method = objClass.getMethod("toString", new Class[]{primClass});
        Object args = new Object[]{primClass.cast(obj)};
        result = (String)method.invoke(null, args);
    }catch(Exception ex){
        //Unknown exception. Send to handler.
        handleException(ex);
    }
    return result;
}

Так что я немного растерялся, правда. У кого-нибудь есть идеи? Любая помощь будет принята с благодарностью.

6 ответов

Решение

Возможно, вы захотите взглянуть на Apache Commons Lang, особенно ToStringBuilder.reflectionToString (). Даже если вы не хотите вводить зависимость только для toString(), это открытый исходный код, поэтому вы можете взглянуть на реализацию.

method.invoke принимает типы Wrapper вместо типов primivtes.

Возможно, я что-то упустил, но obj.toString() сделал бы.

Если вы посмотрите на реализации, это вызывает String.valueOf(value) который в свою очередь вызывает Double.toString(..) или же Long.toString(..) или что угодно. Итак, звоня toString() автоматически вызывает нужный метод. Без какого-либо отражения с вашей стороны.

То, что вы пытаетесь сделать, на самом деле не имеет смысла... когда ваша функция вызывается с примитивным аргументом (например, int), она автоматически помещается в целое число. Так что вы можете просто вызвать obj.toString() для него.....

Однако, если вы действительно хотите сделать что-то особенное с примитивами, вы можете сделать что-то вроде следующего, используя перегрузку метода:

private String toString(Object obj){
  return obj.toString();
}

private String toString(int intValue) {
  // code to return string for the primitive int case, assuming it is different
}

// more overloads for other primitive argument types as needed.....

В некоторых случаях это может быть очень полезным методом для работы с примитивами.

String.valueOf(arg) будет делать это тоже хорошо.

Возможно, есть что-то, чего я не понимаю в вашем вопросе, но для примитива вы можете сделать ""+primitive бросить его в строку.

Непосредственная проблема в вашем коде заключается в том, что obj является объектом, и, следовательно, не может быть экземпляром примитивного типа. (Это должен быть экземпляр соответствующего типа оболочки). primClass.cast(obj) вызов должен потерпеть неудачу для любого класса примитивного типа.

Но если вы просто хотите превратить экземпляр примитивной оболочки в строку, просто вызовите экземпляр toString() метод.

Другие вопросы по тегам