2010-12-11 2 views
1

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

Hello--

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

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

Я в основном пытаюсь создать общую функцию 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; 
} 

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

+1

'toString' методы в' Double, Long, ... 'не делают то, что вы хотите? – khachik

ответ

0

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

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

+0

Ох. Дерьмо. Я не могу в это поверить. Я думал, что пробовал это, и это не сработало, но я, должно быть, просто попытался найти метод, используя класс-оболочку, но не вызвал его. Я решил убедиться, и это сработало. Теперь я чувствую себя совершенно глупо. Большое спасибо. – Apropos

0

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

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

+0

Проблема с этим - метод toString принимает примитивный тип в качестве аргумента - не обертку. Я попытался использовать его как тип оболочки и передать его таким образом, но он выдает исключение из несоответствия типа аргумента. И попытка getMethod toString с типом-оболочкой в ​​качестве аргумента генерирует исключение NoSuchMethodException, как и следовало ожидать. – Apropos

0

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

+0

Технически это не кастинг, а преобразование. Тем не менее, это все еще просто. –

+0

Не могли бы вы рассказать о различии между литьем и конвертированием для примитивов в java? – Istao

0

То, что вы пытаетесь сделать, на самом деле не имеет смысла ... когда ваша функция вызывается с помощью примитивного аргумента (например, int), тогда он автоматически будет помещен в Integer. Таким образом, вы можете также просто позвонить 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..... 

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

+0

obj.toString() не работает (примитивные типы не могут быть разыменованы). Вот почему я решил эту проблему. Я должен был бы знать, что это за оболочка, и вызвать метод toString() таким образом, что я и пытался сделать. – Apropos

0

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

+0

Это намного проще. В то время как то, что я пытался сделать, было интересным экспериментом (и тот факт, что я не мог понять это, был досадным), на самом деле это ответ. Я не могу поверить, что это никогда не появлялось в различных поисках, которые я пробовал. Благодарю. – Apropos

3

Возможно, мне что-то не хватает, но obj.toString() будет делать.

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