2015-01-07 2 views
7

У меня этот код. Почему это не работает? (Рабочий смысл, который он отображает 3) Как я могу это исправить?java access Integer конструктор через отражение

public class Main { 
    public static<V> V copy(V var){ 
     try{ 
      return (V) var.getClass().getConstructor(var.getClass()).newInstance(var); 
     } 
     catch(Exception e){ 
      System.out.println("Copy faield " + e.getMessage() + " "); 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static void main(String[] args) { 
     Integer a = new Integer(3); 
     Integer b = copy(a); 

     System.out.println(a); 
     System.out.println(b); 


    } 
} 

Это выход:

Copy faield java.lang.Integer.<init>(java.lang.Integer) 
    java.lang.NoSuchMethodException: java.lang.Integer.<init>(java.lang.Integer) 
     at java.lang.Class.getConstructor0(Class.java:2818) 
     at java.lang.Class.getConstructor(Class.java:1723) 
     at Main.copy(Main.java:7) 
     at Main.main(Main.java:19) 
    3 
    null 

Спасибо!

+5

Integer имеет только '' int' или String' аргумент конструктора, не 'Integer' не конструктор копирования , При отражении вы не можете автоматически распаковывать параметры. –

+0

Тогда почему это работает Integer c = new Integer (новое целое число (5)); – yonutix

+0

Здесь вы делаете много предположений в общем методе. Не все классы будут иметь конструктор, который принимает значение одного и того же класса. – mikea

ответ

5

Проблема здесь заключается различие между:

Integer.class 
int.class 

Конструктор Integer принимает int параметр, неInteger.

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

AFAIK нет встроенного способа получить primatove класса от класса-оболочки - можно использовать карту и заполнить его с отображениями:

private static final Map<Class<?>, Class<?>> MAP = new HashMap<>() {{ 
    put(Integer.class, int.class); 
    put(Long.class, long.class); 
    // etc 
}}; 

Тогда в вашем методе:

Class<?> type = MAP.containsKey(var.getClass()) ? MAP.get(var.getClass()) : var.getClass(); 
return (V) var.getClass().getConstructor(type).newInstance(var); 

Это нормально, чтобы передать int в качестве значения Integer в значение параметра - это, по крайней мере, автоматически отключается.

+0

Хорошо, я понимаю, спасибо. Если у вас есть идеи, как я могу уклониться от того, что соблюдение цели общего метода, пожалуйста, поделитесь. – yonutix

+0

@CosminMihai См. Код, как обращаться элегантно. Merry Xmas :) – Bohemian

+0

Большое спасибо, надеюсь, что соответствующий класс для примитивного типа char - это символ – yonutix

1

Чтобы действительно понять, почему «новый Integer (новый Integer (5))» работает в то время как отражения не полезно посмотреть на сгенерированный байт-код для первого случая:

ICONST_5 
INVOKESPECIAL java/lang/Integer.<init> (I)V 
INVOKEVIRTUAL java/lang/Integer.intValue()I 
INVOKESPECIAL java/lang/Integer.<init> (I)V 

... в вы можете видеть, что вызов выполняется методом intValue() Integer «под капотом». Таким образом, java-компилятор фактически переводит ваш новый Integer (новый Integer (5)) "в" новый Integer (новый Integer (5) .intValue()) ". Это означает, что он может использовать конструктор, который принимает int.

Поскольку компилятор java не может знать фактический тип времени выполнения переменной для вызова отражений, он не может сделать ничего подобного и может только искать конструктор с фактическим аргументом типа времени выполнения.

+0

Я думаю, что я поставлю некоторые операторы if или коммутатор для классов Integer, Float, Double и Long для разрешения этих конкретных случаев. – yonutix

2

Общий подход к копированию любого объекта в другой объект. Этот класс util доступен в пакете - org.apache.commons.lang3.

Integer c = (Integer) SerializationUtils.clone(a); 
+0

SerializationUtils не входит в стандартную библиотеку, я искал что-то хорошее. – yonutix

+0

Использование зрелой библиотеки, которая уже используется многими пользователями и большими проектами, намного приятнее, чем создавать что-то вместе в течение нескольких часов самостоятельно. Просто мое мнение. –

-1

INT представляет собой тип, но Integer является оболочкой (класс), что использование ИНТ в качестве объекта со многими fonction

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