Kontrollerer om en klasse eksisterer i Java

1. Oversikt

Å sjekke for eksistensen av en klasse kan være nyttig når du bestemmer hvilken implementering av et grensesnitt som skal brukes. Denne teknikken brukes ofte under eldre JDBC-oppsett.

I denne veiledningen, vi vil utforske nyansene ved bruk Class.forName () for å sjekke eksistensen av en klasse i Java-klassestien.

2. Bruke Class.forName ()

Vi kan sjekke for eksistensen av en klasse ved hjelp av Java Reflection, spesielt Class.forName (). Dokumentasjonen viser at a ClassNotFoundException blir kastet hvis klassen ikke kan lokaliseres.

2.1. Når du kan forvente ClassNotFoundException

La oss først skrive en test som sikkert vil kaste en ClassNotFoundException slik at vi kan vite at de positive testene våre er trygge:

@Test (forventet = ClassNotFoundException.class) offentlig ugyldig givenNonExistingClass_whenUsingForName_thenClassNotFound () kaster ClassNotFoundException {Class.forName ("class.that.does.not.exist"); }

Så vi har bevist at en klasse som ikke eksisterer, vil kaste et ClassNotFoundException. La oss skrive en test for en klasse som faktisk eksisterer:

@Test offentlig ugyldighet gittExistingClass_whenUsingForName_thenNoException () kaster ClassNotFoundException {Class.forName ("java.lang.String"); }

Disse testene beviser det løping Class.forName () og ikke fange en ClassNotFoundException tilsvarer den spesifiserte klassen som finnes på klassestien. Dette er imidlertid ikke en perfekt løsning på grunn av bivirkninger.

2.2. Bivirkning: Initialisering av klasse

Det er viktig å påpeke at uten å spesifisere en klasselaster, Class.forName () må kjøre den statiske initialisereren på den valgte klassen. Dette kan føre til uventet oppførsel.

For å eksemplifisere denne oppførselen, la oss lage en klasse som kaster a RuntimeException når den statiske initialiseringsblokken kjøres slik at vi kan vite umiddelbart når den kjøres:

offentlig statisk klasse InitializingClass {statisk {hvis (sann) {// muliggjør kasting av et unntak i en statisk initialiseringsblokk kast nytt RuntimeException (); }}}

Vi kan se fra forName () dokumentasjon som det kaster en ExceptionInInitializerError hvis initialiseringen provosert av denne metoden mislykkes.

La oss skrive en test som forventer en ExceptionInInitializerError når du prøver å finne vår InitializingClass uten å spesifisere en klasselaster:

@Test (forventet = ExceptionInInitializerError.class) offentlig ugyldig givenInitializingClass_whenUsingForName_thenInitializationError () kaster ClassNotFoundException {Class.forName ("path.to.InitializingClass"); }

Siden utførelsen av en klasses statisk initialiseringsblokk er en usynlig bivirkning, kan vi nå se hvordan det kan forårsake ytelsesproblemer eller til og med feil. La oss se på hvordan du hopper over initialisering av klassen.

3. Fortelle Class.forName () å hoppe over initialisering

Heldigvis for oss er det en overbelastet metode for forName (), som godtar en klasselaster og om initialisering av klassen skal utføres.

I følge dokumentasjonen er følgende samtaler ekvivalente:

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

Ved å endre ekte til falsk, kan vi nå skrive en test som sjekker for eksistensen av vår InitializingClassuten å utløse den statiske initialiseringsblokken:

@Test offentlig ugyldighet givenInitializingClass_whenUsingForNameWithoutInitialization_thenNoException () kaster ClassNotFoundException {Class.forName ("path.to.InitializingClass", false, getClass (). GetClassLoader ()); }

4. Java 9-moduler

For Java 9+-prosjekter er det en tredje overbelastning av Class.forName (), som godtar en Modul og en String klassenavn. Denne overbelastningen kjører ikke klasseinitialiseringen som standard. Spesielt kommer den tilbake null når den etterspurte klassen ikke eksisterer i stedet for å kaste a ClassNotFoundException.

5. Konklusjon

I denne korte opplæringen har vi eksponert bivirkningen av klasseinitialisering når du bruker Class.forName () og har funnet ut at du kan bruke forName () overbelastning for å forhindre at det skjer.

Kildekoden med alle eksemplene i denne opplæringen finner du på GitHub.


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