2015-01-07 21 views
7

Mam ten kod. Dlaczego to nie działa? (Działające znaczenie, które wyświetla 3) Jak mogę to naprawić?java dostęp Integer konstruktor przez odbicie

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


    } 
} 

To wyjście:

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 

Dzięki!

+5

Integer ma tylko '' String' int' lub argumentów konstruktorów, nie 'Integer' Konstruktor kopiujący . Dzięki odbiciu nie można automatycznie rozpakować parametrów. –

+0

Dlaczego więc działa Integer c = new Integer (new Integer (5)); – yonutix

+0

Podejmujesz tutaj wiele założeń w ogólnej metodzie. Nie wszystkie klasy będą miały konstruktor, który przyjmuje wartość tej samej klasy. – mikea

Odpowiedz

5

Tutaj problemem jest rozróżnienie pomiędzy:

Integer.class 
int.class 

Konstruktor Integer bierze parametr int, nieInteger.

Aby twoja magiczna metoda zadziałała, musisz wykonać specjalną kontrolę typu, a jeśli jest to klasa opakowawcza, poszukaj konstruktora, którego parametrem jest odpowiedni typ podstawowy.

AFAIK nie ma zbudowany w sposób, aby uzyskać primatove klasy z klasy otoki - można korzystać z mapy i wypełnić go z odwzorowań:

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

Następnie w metodzie:

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

Można przesłać int jako Integer w wartości parametru - co najmniej automatycznie zostanie rozpakowane.

+0

Ok, rozumiem, dziękuję. Jeśli masz pojęcie, jak mogę uniknąć tego celu, zachowując cel metody ogólnej, podziel się. – yonutix

+0

@CosminMihai Zobacz kod, jak obsługiwać elegancko. Merry Xmas :) – Bohemian

+0

Dziękuję bardzo, mam nadzieję, że odpowiednia klasa dla char prymitywnego typu jest Character – yonutix

1

Aby naprawdę zrozumieć, dlaczego "new Integer (nowe Integer (5))" dzieła podczas odbicia nie jest to przydatne, aby spojrzeć na wygenerowanego kodu bajtowego w pierwszym przypadku:

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

... jak widać, że wywoływane jest połączenie do metody intValue() liczby całkowitej "pod maską". Tak więc kompilator java faktycznie tłumaczy twoją "nową liczbę całkowitą (nową liczbę całkowitą (5))" na "nową liczbę całkowitą (nową liczbę całkowitą (5) .intValue())". Oznacza to, że może użyć konstruktora, który przyjmuje int.

Ponieważ kompilator java nie może znać rzeczywistego typu środowiska wykonawczego zmiennej dla wywołania reflections, nie może zrobić nic podobnego i może jedynie szukać konstruktora z rzeczywistym argumentem typu środowiska wykonawczego.

+0

Myślę, że wstawię niektóre instrukcje if lub przełącznik dla klas Integer, Float, Double i Long, aby rozwiązać te konkretne przypadki – yonutix

2

Ogólne podejście polegające na kopiowaniu dowolnego obiektu do innego obiektu. Ta klasa wykorzystania jest dostępna w pakiecie - org.apache.commons.lang3.

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

SerializationUtils nie znajduje się w standardowej bibliotece, szukałem czegoś miłego. – yonutix

+0

Korzystanie z dojrzałej biblioteki, która jest już używana przez wielu użytkowników i duże projekty, jest o wiele przyjemniejsze niż samodzielne stawianie czegoś w kilka godzin. Tylko moja opinia. –

-1

int jest typem ale Integer jest opakowaniem (klasa), że używanie int jako obiekt z wieloma FONCTION

Powiązane problemy