łatwe proste pytanie: jak załadowć dynamicznie klasę załóżmy z pliku C:\MojaKlasa.class ?
Class.forName(MojaKlasa);
To wcale nie jest takie proste, pytanie tez ze zadane - czy klasa MojaKlasa jest widoczna? czy ten katalog jest w classpath? jesli tak to wasze propozycje zadzialaja, ale moze kolega chce po prostu zaladowac jakas arbitralna klase z dowolnego miejca? Wtedy musi uzyc np URLClassLoadera czy innego wynalazku.
Pozdro
No właśnie.
Taka linika kodu niestety mnie nie zadowala
Class.forName(MojaKlasa);
Zrobię tak: przedstawię wam mój przykład, a wy go poprawicie :P
Krok 1:
piszę klasę o nazwie Dodawacz:
public class Dodawacz
{
public Dodawacz()
{
}
public static void main(String args[])
{
}
public int Dodaj(int i, int j)
{
return i + j;
}
public static int DodajStatycznie(int i, int j)
{
return i + j;
}
}
i umieszczam cały kod w pliku Dodawacz.java, następnie kompiluje do Dodawacz.class i umieszczam na C:\
Krok 2:
Piszę kawałek kodu odpowiedzialny za wczytanie Dodawacza:
File file = new File("C:\\Dodawacz.class");
URL[] urlsToLoadFrom = new URL [] { file.toURI().toURL() } ;
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom) ;
Class klasa = Class.forName("Dodawacz", false, loader1);
i co?
java.lang.ClassNotFoundException: Dodawacz
Możecie mi wytłumaczyc co źle zrobiłem?
nie jestem na bank pewien ale urlclassloader bierze url ktore wskazuja albo na katalog z plikami class albo do jarow - jesli konczy sie na / lub \ oznacza to ze to jest katalog, jesli nie to jest to jar
powinno to wygladac zatem tak:
File file = new File("C:\\");
URL[] urlsToLoadFrom = new URL[] { file.toURI().toURL() };
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom);
Class klasa = Class.forName("Dodawacz", false, loader1);
pozdro
Dzięki. Wspólnymi siłami udało się.
A więc tak: umieszczamy plik Dodawacz.class na C:
A kod programu ładującego Dodawacza z tego pliku wygląda tak:
URL[] urlsToLoadFrom = new URL [] { new File("C:/").toURI().toURL() } ; // poprawnie: "C:/" , nie poprawnie: "C:\\"
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom) ;
Class klasa = Class.forName("Dodawacz", true, loader1);
Method m = klasa.getMethod("DodajStatycznie", new Class[] { int.class, int.class });
int wynik = (Integer)(m.invoke(null, new Object[] { 3, 6 }));
Ale mam jeszcze kilka pytań:
- da się załadować klasę z jara? A jeśli tak to w jaki sposób?
- czy można w jakiś sposób załadować klasę ze strumienia lub z tablicy bajtów?
- c:/jest poprawne poniewaz to jest sciezka do pliku, url tworzy sie pozniej i sam przeksztalca te sciezki
- da sie z jara - wystarxzy ze jako jeden z url bedzie wskazywal na jara a nie na katalog i juz dalej to samo - robisz to new File("c:\jakisJar.jar").toUri().toUrl()
- w sumie wszzytskie klasy sa wczytywane z tablicy bajtow - ClassLoader ma metode defineClass ktora bierze miedzy innymi tablice bajtow, ktora jest jakostam wyszukiwana w metodzie findClass(nazwa) - wczytywana - sa to metody protected i sa nadpisywane w klasach pochodnych - mozes wiec napisac sobie dajmy na to MemoryByteArrayClassLoader ktory robi to:
- szuka gdzies w pamieci np w mapie taablicy bajtow (metoda findClass)
- wczytuje ja (metoda defineClass)
i juz
warto poczytac o klasie ClassLoader w API
pozdro