odczytywanie parametrów konstruktorów i dynamiczne wstawianie im wartości.

0

Witam.
Ostatnio z całych sił próbuję znaleźć rozwiązanie takie oto problemu.
Załóżmy że mam bardzo wiele klas.
W każdej klasie jest inny konstruktor który przyjmuje odmienne parametry.
W innej klasie programu jest metoda która tworzy obiekty poszczególnych klas (każda klasa jest encją i w tej metodzie tworzone są obiekty klasy które odzwierciedlają kolumny tabeli).
Czy jest sposób aby proces tworzenia tych obiektów nieco zautomatyzować?

 
createConnection(); //metoda odpowiedzialna za utworzenie połączenia
Statement stmt = null;
String query = "Select * From Tab1" //tu dla przykłady Tab1, oczywiście z tą nazwą nie byłoby problemu bo można stworzyć tablicę z nazwami wszystkich tabel na których pracuję.... 
stmt = conn.createStatement();
ResultSet rset =stmt.executeQuery(query);
while (rset.next()) //tutaj wyciągane są wartości, które chciałbym aby posłużyły do utworzenia obiektu klasy NazwaKlasy
{
   int zm1=rset.getInt("kol1);
   int zm2=rset.getInt("kol2);
   int zm2=rset.getInt("kol3);
   //itd. liczba kolumn jest zmienna, wiem że liczbę kolumn też bez problemu można odczytać choćby z meta.getColumns(null,null,"Tab1",null); to opakować w pętlę while() i iterowalibyśmy po poszczególnych kolumnach. Ale jak to "wprowadzić" do parametrów??
NazwaKlasy klasa = new NazwaKlasy(zm1, zm2, zm3); //to najważniejsza część programu czyli tworzenie obiektów klasy NazwaKlasa na podstawie wartości parametrów uzyskanych z bazy danych.
InnaKlasa.add(klasa); //tutaj wywoływana jest metoda dodająca elementy klasy NazwaKlasy do listy<NazwaKlasy>
}

Czyli podsumowując: szukam możliwości odczytania nazw parametrów z konstruktora każdej z klasy i wstawienia tych danych jako parametry, a przy tym aby wartością tych paramentów były dane odczytane z tabeli tak jak to jest we fragmencie kodu zamieszczonym powyżej.
Mam nadzieję że "takie rzeczy są nie tylko w Erze" ;-)

Gdybym miał pięć tabel to bym się nie zastanawiał tylko napisał "z palca" kod, jednak przy pięćdziesięciu paru tabelach to będzie "nieco" pracochłonne.
Z góry dziękuje za wszelkie pomysły!

1

Najprawdopodobniej będziesz musiał skorzystać z refleksji oraz klasy Constructor. Tutaj masz przykład wywołania konstruktora z parametrami (i więcej podobnych przykładów):
http://www.java2s.com/Code/Java/Language-Basics/ObjectReflectioninvokeconstructorwithparameters.htm
A tu podstawy refleksji:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/

Największym Twoim problemem do zakodowania będzie jedynie określenie na podstawie argumentów jakie wyciągniesz z bazy, którego konstruktora z listy konstruktorów wybrać do wywołania (a przecież może nie pasować żaden lub lista będzie miała tylko jedną pozycję), a następnie przypisanie jego parametrom tych argumentów. Na koniec wywołanie Constructor.newInstance(Object[] arguments) i albo rzutowanie do właściwego typu, aby InnaKlasa.add() miała właściwy argument, albo przeprojektowanie add() tak aby od razu łykała utworzony obiekt, którego referencja jest ogólnego typu Object.

0

Tak właśnie myślałem że trzeba szukać w "Reflection", czytam od rana tutorial Oracle. Ale dla mnie jest to totalna nowość, więc będę wdzięczny za jakieś jeszcze podpowiedzi.

0

Moją podpowiedzią jest by nie korzystać z reflection jeśli skupiasz się na wydajności aplikacji. Jest ona bardziej procesorożerna:
http://stackoverflow.com/questions/435553/java-reflection-performance
http://www.jguru.com/faq/view.jsp?EID=246569

0

Witam ponownie.
O ile prawie sobie poradziłem to mam jeszcze jeden problem i może ktoś pomoże mi go rozwiązać.
Zatrzymałem się na tworzeniu newInstance, oto kod z którym nie mogę sobie poradzić.

NazwaKlasy nk1 = (NazwaKlasy)ctor.newInstance(wartosci);
 

gdzie ctor to Constructor o określonych parametrach (to wszystko działa ok) a wartości to tablica Integer[]
A mój problem to jak NazwaKlasy zrobić jako zmienną?
Próbowałem stworzyć tablicę Class[] tablica ={NazwaKlasy.class, NazwaKlasy2.class} itp ale to nie przechodzi.

 
tablica[i] nk1 = (tablica[i])ctor.newInstance(wartosci); //tak nie zadziała!!!

Z góry dziękuję za jakąś poradę!

1

A po co chcesz mieć NazwaKlasy jako zmienną? Typ zmiennej musi być znany podczas kompilacji, więc oczywiste, że nie przechodzi. Możesz przecież operować na Objectach, a tylko wtedy, kiedy sam tego będziesz potrzebował, rzutować na konkretny typ.

0

Znany interfejs ktory klasy tworzone refleksja implementuja i na ktory sa rzutowane.

0

Musiałem "przetrawić" Twoją podpowiedź i faktycznie miałeś 100% racji...
w moim przykładzie wystarczy zrobić newInstance na typ Object czyli:

 
Object obiekt = ctor.newInstance(wartosci);

co jest równoznaczne

 
NazwaKlasy nkl = (NazwaKlasy)ctor.newInstance(wartosci);

Dziękuję bardzo za podpowiedź :-)

0
lukiz napisał(a)

Musiałem "przetrawić" Twoją podpowiedź i faktycznie miałeś 100% racji...
w moim przykładzie wystarczy zrobić newInstance na typ Object czyli:

Object obiekt = ctor.newInstance(wartosci);

> 
> co jest równoznaczne
> <code> 
NazwaKlasy nkl = (NazwaKlasy)ctor.newInstance(wartosci);

Dziękuję bardzo za podpowiedź :-)

Wcale nie jest jednoznaczne - wystarczy ze NazwaKlasy ma jakas metode ktora chcesz wykonac - nie masz jak, pomijajac refleksje.
Rozwiazuje sie to tak ze masz jakis interfejs ktory jest znany w czasie kompilacji, klasy ktore tworzysz dynamicznie (takie jakby pluginy) implementuja ten interfejs, i mozesz na niego rzutowac.

1 użytkowników online, w tym zalogowanych: 0, gości: 1