Controleren of er een klasse bestaat in Java

1. Overzicht

Het controleren op het bestaan ​​van een klasse kan handig zijn om te bepalen welke implementatie van een interface moet worden gebruikt. Deze techniek wordt vaak gebruikt tijdens oudere JDBC-opstellingen.

In deze tutorial we zullen de nuances van het gebruik onderzoeken Class.forName () om het bestaan ​​van een klasse in het Java-klassenpad te controleren.

2. Met behulp van Class.forName ()

We kunnen het bestaan ​​van een klasse controleren met behulp van specifiek Java Reflection Class.forName (). Uit de documentatie blijkt dat a ClassNotFoundException wordt gegenereerd als de klasse niet kan worden gevonden.

2.1. Wanneer te verwachten ClassNotFoundException

Laten we eerst een test schrijven die zeker een ClassNotFoundException zodat we kunnen weten dat onze positieve tests veilig zijn:

@Test (verwacht = ClassNotFoundException.class) openbare ongeldige gegevenNonExistingClass_whenUsingForName_thenClassNotFound () gooit ClassNotFoundException {Class.forName ("class.that.does.not.exist"); }

We hebben dus bewezen dat een klasse die niet bestaat, een ClassNotFoundException. Laten we een test schrijven voor een klasse die inderdaad bestaat:

@Test openbare ongeldige gegevenExistingClass_whenUsingForName_thenNoException () gooit ClassNotFoundException {Class.forName ("java.lang.String"); }

Deze tests bewijzen dat rennen Class.forName () en het niet vangen van een ClassNotFoundException is gelijk aan de opgegeven klasse die bestaat op het klassenpad. Dit is echter niet helemaal een perfecte oplossing vanwege bijwerkingen.

2.2. Bijwerking: Klasse-initialisatie

Het is essentieel erop te wijzen dat, zonder een klassenlader op te geven, Class.forName () moet de statische initialisatie uitvoeren op de gevraagde klasse. Dit kan tot onverwacht gedrag leiden.

Laten we, om dit gedrag te illustreren, een klasse maken die een RuntimeException wanneer het statische initialisatieblok wordt uitgevoerd, zodat we onmiddellijk kunnen weten wanneer het wordt uitgevoerd:

openbare statische klasse InitializingClass {statisch {if (true) {// inschakelen van een uitzondering in een statisch initialisatieblok gooien nieuwe RuntimeException (); }}}

We kunnen zien aan de forName () documentatie dat het een ExceptionInInitializerError als de initialisatie die door deze methode wordt veroorzaakt, mislukt.

Laten we een test schrijven die een ExceptionInInitializerError bij het vinden van onze InitializingClass zonder een klassenlader op te geven:

@Test (verwacht = ExceptionInInitializerError.class) openbare ongeldige gegevenInitializingClass_whenUsingForName_thenInitializationError () gooit ClassNotFoundException {Class.forName ("path.to.InitializingClass"); }

Aangezien de uitvoering van het statische initialisatieblok van een klasse een onzichtbaar neveneffect is, kunnen we nu zien hoe dit prestatieproblemen of zelfs fouten kan veroorzaken. Laten we eens kijken hoe we de initialisatie van de klas kunnen overslaan.

3. Vertellen Class.forName () om initialisatie over te slaan

Gelukkig voor ons is er een overbelaste methode van forName (), die een klassenlader accepteert en of de klasseninitialisatie moet worden uitgevoerd.

Volgens de documentatie zijn de volgende oproepen equivalent:

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

Door te veranderen waar naar false, kunnen we nu een test schrijven die controleert op het bestaan ​​van onze InitializingClasszonder het statische initialisatieblok te activeren:

@Test openbare leegte gegevenInitializingClass_whenUsingForNameWithoutInitialization_thenNoException () gooit ClassNotFoundException {Class.forName ("path.to.InitializingClass", false, getClass (). GetClassLoader ()); }

4. Java 9-modules

Voor Java 9+ -projecten is er een derde overbelasting van Class.forName (), die een Module en een Draad naam van de klasse. Door deze overbelasting wordt de klasseninitialisatie niet standaard uitgevoerd. Het keert ook met name terug nul wanneer de gevraagde klasse niet bestaat in plaats van een ClassNotFoundException.

5. Conclusie

In deze korte zelfstudie hebben we de bijwerking van klasseninitialisatie bij gebruik van Class.forName () en hebben ontdekt dat u de forName () overbelasting om dat te voorkomen.

De broncode met alle voorbeelden in deze tutorial is te vinden op GitHub.


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