Kontrola, či trieda existuje v prostredí Java

1. Prehľad

Kontrola existencie triedy by mohla byť užitočná pri rozhodovaní, ktorú implementáciu rozhrania použiť. Táto technika sa bežne používa počas starších nastavení JDBC.

V tomto návode preskúmame nuansy používania Class.forName () skontrolovať existenciu triedy v triede Java.

2. Pomocou Class.forName ()

Môžeme skontrolovať existenciu triedy pomocou Java Reflection, konkrétne Class.forName (). Dokumentácia ukazuje, že a ClassNotFoundException bude vyhodené, ak triedu nebude možné lokalizovať.

2.1. Kedy očakávať ClassNotFoundException

Najprv si napíšme test, ktorý určite hodí ClassNotFoundException aby sme vedeli, že naše pozitívne testy sú bezpečné:

@Test (očakáva sa = ClassNotFoundException.class) public void givenNonExistingClass_whenUsingForName_thenClassNotFound () hodí ClassNotFoundException {Class.forName ("class.that.does.not.exist"); }

Takže sme dokázali, že trieda, ktorá neexistuje, bude hodiť a ClassNotFoundException. Poďme napísať test pre triedu, ktorá skutočne existuje:

@ Test public void givenExistingClass_whenUsingForName_thenNoException () hodí ClassNotFoundException {Class.forName ("java.lang.String"); }

Tieto testy to dokazujú bežiaci Class.forName () a nechytať a ClassNotFoundException je ekvivalentná so zadanou triedou existujúcou v triede cesty. Nie je to však celkom dokonalé riešenie kvôli vedľajším účinkom.

2.2. Vedľajší efekt: Inicializácia triedy

Je nevyhnutné zdôrazniť, že bez zadania nakladača triedy, Class.forName () musí spustiť statický inicializátor v požadovanej triede. To môže viesť k neočakávanému správaniu.

Na ilustráciu tohto správania vytvorme triedu, ktorá hodí a RuntimeException keď je vykonaný jeho statický inicializačný blok, aby sme okamžite vedeli, kedy je vykonaný:

verejná statická trieda InitializingClass {static {if (true) {// povoliť vyvolanie výnimky v statickom inicializačnom bloku throw new RuntimeException (); }}}

Môžeme vidieť z pre meno () dokumentáciu, ktorú hodí ExceptionInInitializerError ak zlyhá inicializácia vyvolaná touto metódou.

Poďme napísať test, ktorý bude očakávať ExceptionInInitializerError pri pokuse nájsť našu InitializingClass bez zadania nakladača triedy:

@Test (očakáva sa = ExceptionInInitializerError.class) public void givenInitializingClass_whenUsingForName_thenInitializationError () hodí ClassNotFoundException {Class.forName ("path.to.InitializingClass"); }

Pretože vykonávanie statického inicializačného bloku triedy je neviditeľným vedľajším účinkom, teraz vidíme, ako by to mohlo spôsobiť problémy s výkonom alebo dokonca chyby. Pozrime sa, ako preskočiť inicializáciu triedy.

3. Rozprávanie Class.forName () preskočiť inicializáciu

Našťastie pre nás existuje preťažená metóda forName (), ktorý prijíma načítavač triedy a či má byť vykonaná inicializácia triedy.

Podľa dokumentácie sú nasledujúce hovory rovnocenné:

Class.forName ("Foo") Class.forName ("Foo", true, this.getClass (). GetClassLoader ())

Zmenou pravda do nepravdivé, teraz môžeme napísať test, ktorý kontroluje existenciu nášho InitializingClassbez spustenia jeho statického inicializačného bloku:

@ Test public void givenInitializingClass_whenUsingForNameWithoutInitialization_thenNoException () hodí ClassNotFoundException {Class.forName ("path.to.InitializingClass", false, getClass (). GetClassLoader ()); }

4. Moduly Java 9

Pre projekty Java 9+ je tu tretie preťaženie Class.forName (), ktorá prijíma a Modul a a String názov triedy. Toto preťaženie predvolene nespúšťa inicializátor triedy. Tiež sa pozoruhodne vracia nulový keď požadovaná trieda neexistuje, skôr ako hádzanie a ClassNotFoundException.

5. Záver

V tomto krátkom tutoriáli sme odhalili vedľajší efekt inicializácie triedy pri používaní Class.forName () a zistili ste, že môžete použiť pre meno () aby k tomu nedošlo.

Zdrojový kód so všetkými príkladmi v tomto tutoriále nájdete na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found