2009-07-07 17 views
6

Piszę metodę deserializacji, która konwertuje XML do obiektu Java. Chciałbym to zrobić dynamicznie i unikać pisania sztywno zakodowanych odniesień do określonych typów.Jak utworzyć instancję ArrayList <?> i dodać element poprzez odbicie za pomocą Java?

Na przykład jest to uproszczona wersja jednej z moich klas.

public class MyObject { 
    public ArrayList<SubObject> SubObjects = new ArrayList<SubObject>(); 
} 

Oto okrojona wersja metody:

public class Serializer {  
    public static <T> T fromXml(String xml, Class<T> c) { 
     T obj = c.newInstance();  
     Field field = obj.getClass().getField("SubObjects");  
     //help : create instance of ArrayList<SubObject> and add an item 
     //help#2 : field.set(obj, newArrayList); 

     return obj; 
    } 
} 

Wywołanie tej metody może wyglądać następująco:

MyObject obj = Serializer.fromXml("myxmldata", MyObject.class); 

Wybacz mi, jeśli jest to niemały problem jak ja programista C# uczący się języka Java.

Dzięki!

+0

Czy możesz podać przykład pliku XML? – CookieOfFortune

+0

Co jeśli subObjects jest zadeklarowane jako interfejs (np. Lista)? –

Odpowiedz

7

powinno być coś całkiem blisko:

Object list = field.getType().newInstance(); 

Method add = List.class.getDeclaredMethod("add",Object.class); 

add.invoke(list, addToAddToList); 

Nadzieja to pomaga.

+0

Dzięki, tego właśnie szukałem. Czy możesz również wyjaśnić, w jaki sposób mogę uzyskać informacje o typie SubObject w instancji listy? – user82334

+0

To jest ten fragment, którego nie ma, ogólne informacje o typach kolekcji nie są dostępne w środowisku wykonawczym w Javie. Generics są zaimplementowane w kompilatorze. –

+0

Domyślam się, że bit, którego szukasz, to wiedzieć, do której klasy należy utworzyć instancję, aby dodać nowy obiekt listy? Ta informacja po prostu nie jest dostępna, możesz dodać ją do siebie, tworząc adnotację i dodając adnotację do pola SubObjects, coś takiego jak @SerialisationType (SubObject.class) –

0

W java generics są po prostu cukrem składniowym i nie istnieją w środowisku wykonawczym. Dlatego nie można programowo tworzyć ogólnych obiektów w środowisku wykonawczym. Spróbuj utworzyć ogólną listę i przesyłaj (jednak nie jestem pewien, ponieważ moje doświadczenie jest ograniczone GWT).

+0

To nie do końca prawda. Jeśli masz klasę MyArray, która rozszerza ArrayList , to masz informacje o typie w czasie wykonywania. Możliwe jest również utworzenie instancji obiektu w czasie wykonywania, który kod rzuca na "sparametryzowany obiekt" - rzutowanie nie będzie miało znaczenia, a kompilator wygeneruje ostrzeżenie sprawdzane pod kątem typu: –

+0

@Oxbow: Klasa będzie przechowywać sparametryzowany typ sygnatury metod w środowiskach wykonawczych. Nie wierzę w indywidualną kolekcję. – Jherico

0

Będziesz musiał utworzyć surowy wpisany typ List (tj. Bez parametrów typu).

List subs = deserialize(...); 

Jeśli było ustawić surowe wpisane List na swojej klasie bezpośrednio:

obj.setSubObjects(subs); //You'll get an "unchecked cast" warning at compile time 

Chociaż kompilator wygeneruje ostrzeżenie, to jest kod Java prawną i będzie działać dobrze na starcie, ponieważ informacje o typie parametrów są tracone (tzn. w czasie wykonywania nie ma różnicy między List i List<SomeClass>). Możesz oczywiście ustawić to również refleksyjnie.

3

Wygląda na to, że prawdziwy problem dotyczy obiektów XML. Jeśli tak jest (a ponieważ jesteś nowy w Javie), lepszym rozwiązaniem niż toczenia własne mogą być zbadanie istniejących technologii, takich jak:

Powiązane problemy