Een inleiding tot Apache Commons Lang 3

1. Overzicht

De Apache Commons Lang 3-bibliotheek is een populair, compleet pakket van hulpprogramma-klassen, bedoeld om de functionaliteit van de Java API uit te breiden.

Het repertoire van de bibliotheek is behoorlijk rijk, variërend van string-, array- en nummermanipulatie, reflectie en gelijktijdigheid tot de implementaties van verschillende geordende datastructuren, zoals paren en triples (algemeen bekend als tuples).

In deze tutorial we zullen een diepe duik nemen in de meest bruikbare utility-klassen van de bibliotheek.

2. De afhankelijkheid van Maven

Om Apache Commons Lang 3 te gaan gebruiken, moeten we zoals gewoonlijk eerst de Maven-afhankelijkheid toevoegen:

 org.apache.commons commons-lang3 3.8 

3. Het StringUtils Klasse

De eerste utility-klasse die we in deze inleidende samenvatting behandelen, is StringUtils.

Zoals de naam suggereert, StringUtils stelt ons in staat om een ​​aantal nul-veilige s uit te voerentrings operaties die degene die aanvullen / uitbreiden java.lang.String biedt uit de doos.

Laten we beginnen met het presenteren van de set hulpprogramma-methoden die verschillende controles uitvoeren op een bepaald draad, zoals het bepalen of de draad is leeg, leeg, kleine letters, hoofdletters, alfanumeriek enzovoort:

@Test openbare leegte whenCalledisBlank_thenCorrect () {assertThat (StringUtils.isBlank ("")). IsTrue (); } @Test openbare leegte whenCalledisEmpty_thenCorrect () {assertThat (StringUtils.isEmpty ("")). IsTrue (); } @Test openbare leegte whenCalledisAllLowerCase_thenCorrect () {assertThat (StringUtils.isAllLowerCase ("abd")). IsTrue (); } @Test openbare leegte whenCalledisAllUpperCase_thenCorrect () {assertThat (StringUtils.isAllUpperCase ("ABC")). IsTrue (); } @Test openbare leegte whenCalledisMixedCase_thenCorrect () {assertThat (StringUtils.isMixedCase ("abC")). IsTrue (); } @Test openbare leegte whenCalledisAlpha_thenCorrect () {assertThat (StringUtils.isAlpha ("abc")). IsTrue (); } @Test openbare leegte whenCalledisAlphanumeric_thenCorrect () {assertThat (StringUtils.isAlphanumeric ("abc123")). IsTrue (); } 

Natuurlijk is de StringUtils class implementeert vele andere methoden, die we hier voor de eenvoud hebben weggelaten.

Voor enkele andere aanvullende methoden die een bepaald type conversie-algoritme controleren of toepassen op een gegeven draad, kijk dan in deze tutorial.

Degenen die we hierboven hebben behandeld, zijn echt eenvoudig, dus de eenheidstests moeten voor zichzelf spreken.

4. Het ArrayUtils Klasse

De ArrayUtils class implementeert een reeks hulpprogramma-methoden waarmee we arrays in veel verschillende vormen en vormen kunnen verwerken en controleren.

Laten we beginnen met de twee overbelaste implementaties van de toString () methode, die een draad vertegenwoordiging van het gegeven array en een specifiek draad wanneer de array is niets:

@Test public void whenCalledtoString_thenCorrect () {String [] array = {"a", "b", "c"}; assertThat (ArrayUtils.toString (array)) .isEqualTo ("{a, b, c}"); } @Test public void whenCalledtoStringIfArrayisNull_thenCorrect () {assertThat (ArrayUtils.toString (null, "Array is null")) .isEqualTo ("Array is null"); } 

Vervolgens hebben we de hasCode () en in kaart brengen() methoden.

De eerste genereert een aangepaste hashCode-implementatie voor een matrix, terwijl de laatste een array naar een Kaart:

@Test openbare leegte whenCalledhashCode_thenCorrect () {String [] array = {"a", "b", "c"}; assertThat (ArrayUtils.hashCode (array)) .isEqualTo (997619); } @Test public void whenCalledtoMap_thenCorrect () {String [] [] array = {{"1", "een",}, {"2", "twee",}, {"3", "drie"}}; Map map = nieuwe HashMap (); map.put ("1", "een"); map.put ("2", "twee"); map.put ("3", "drie"); assertThat (ArrayUtils.toMap (array)) .isEqualTo (kaart); }

Laten we ten slotte eens kijken naar het isSameLength () en index van() methoden.

De eerste wordt gebruikt om te controleren of twee arrays dezelfde lengte hebben, en de laatste om de index van een bepaald element te krijgen:

@Test openbare leegte whenCalledisSameLength_thenCorrect () {int [] array1 = {1, 2, 3}; int [] array2 = {1, 2, 3}; assertThat (ArrayUtils.isSameLength (array1, array2)) .isTrue (); } @Test openbare leegte whenCalledIndexOf_thenCorrect () {int [] array = {1, 2, 3}; assertThat (ArrayUtils.indexOf (array, 1, 0)) .isEqualTo (0); } 

Net als bij de StringUtils klasse, ArrayUtils veel meer aanvullende methoden implementeren. In deze tutorial leest u er meer over.

In dit geval hebben we alleen de meest representatieve getoond.

5. Het NumberUtils Klasse

Een ander belangrijk onderdeel van Apache Commons Lang 3 is de klasse NumberUtils.

Zoals verwacht, de klasse biedt een uitgebreid aantal hulpprogramma-methoden, gericht op het verwerken en manipuleren van numerieke typen.

Laten we eens kijken naar de overbelaste implementaties van het vergelijken() methode, die de gelijkheid van verschillende primitieven vergelijkt, zoals int en lang:

@Test openbare leegte whenCalledcompareWithIntegers_thenCorrect () {assertThat (NumberUtils.compare (1, 1)) .isEqualTo (0); } @Test openbare leegte whenCalledcompareWithLongs_thenCorrect () {assertThat (NumberUtils.compare (1L, 1L)) .isEqualTo (0); }

Daarnaast bestaan ​​er implementaties van vergelijken() die opereren byte en kort, die erg lijken op de bovenstaande voorbeelden.

De volgende in deze recensie zijn de createNumber () en isDigit () methoden.

Met de eerste kunnen we een numerieke weergave maken van a draad, terwijl de tweede controleert of een draad bestaat alleen uit cijfers:

@Test openbare leegte whenCalledcreateNumber_thenCorrect () {assertThat (NumberUtils.createNumber ("123456")) .isEqualTo (123456); } @Test openbare leegte whenCalledisDigits_thenCorrect () {assertThat (NumberUtils.isDigits ("123456")). IsTrue (); } 

Als het gaat om het vinden van de mix- en max-waarden van een meegeleverde array, is de NumberUtils class biedt sterke ondersteuning voor deze bewerkingen door de overbelaste implementaties van het min () en max () methoden:

@Test openbare leegte whenCalledmaxwithIntegerArray_thenCorrect () {int [] array = {1, 2, 3, 4, 5, 6}; assertThat (NumberUtils.max (array)) .isEqualTo (6); } @Test openbare leegte whenCalledminwithIntegerArray_thenCorrect () {int [] array = {1, 2, 3, 4, 5, 6}; assertThat (NumberUtils.min (array)). isEqualTo (1); } @Test openbare leegte whenCalledminwithByteArray_thenCorrect () {byte [] array = {1, 2, 3, 4, 5, 6}; assertThat (NumberUtils.min (array)) .isEqualTo ((byte) 1); }

6. De Fractie Klasse

Werken met breuken is prima als we een pen en een stuk papier gebruiken. Maar moeten we de complexiteit van dit proces doorlopen bij het schrijven van code? Niet echt.

De Fractie klasse maakt het optellen, aftrekken en vermenigvuldigen van breuken in een handomdraai:

@Test openbare leegte whenCalledgetFraction_thenCorrect () {assertThat (Fraction.getFraction (5, 6)). IsInstanceOf (Fraction.class); } @Test openbare leegte gegevenTwoFractionInstances_whenCalledadd_thenCorrect () {Fraction fraction1 = Fraction.getFraction (1, 4); Breukfractie2 = Breuk.getFractie (3, 4); assertThat (fraction1.add (fraction2) .toString ()). isEqualTo ("1/1"); } @Test openbare leegte gegevenTwoFractionInstances_whenCalledsubstract_thenCorrect () {Fraction fraction1 = Fraction.getFraction (3, 4); Breukfractie2 = Breuk.getFractie (1, 4); assertThat (fraction1.subtract (fraction2) .toString ()). isEqualTo ("1/2"); } @Test openbare leegte gegevenTwoFractionInstances_whenCalledmultiply_thenCorrect () {Fraction fraction1 = Fraction.getFraction (3, 4); Breukfractie2 = Breuk.getFractie (1, 4); assertThat (fraction1.multiplyBy (fraction2) .toString ()). isEqualTo ("3/16"); }

Hoewel bewerkingen met breuken zeker niet de meest voorkomende taak zijn die we in ons dagelijkse ontwikkelingswerk zullen moeten aanpakken, is de Fractie class biedt waardevolle ondersteuning om deze bewerkingen op een eenvoudige manier uit te voeren.

7. Het SystemUtils Klasse

Soms hebben we wat dynamische informatie nodig over verschillende eigenschappen en variabelen van het onderliggende Java-platform of het besturingssysteem.

Apache Commons Lang 3 biedt de SystemUtils klasse om dit op een pijnloze manier te bereiken.

Laten we bijvoorbeeld eens kijken naar de getJavaHome (), getUserHome () en isJavaVersionAtLeast () methoden:

@Test openbare leegte whenCalledgetJavaHome_thenCorrect () {assertThat (SystemUtils.getJavaHome ()) .isEqualTo (nieuw bestand ("pad / naar / java / jdk")); } @Test openbare leegte whenCalledgetUserHome_thenCorrect () {assertThat (SystemUtils.getUserHome ()) .isEqualTo (nieuw bestand ("pad / naar / gebruiker / huis")); } @Test openbare leegte whenCalledisJavaVersionAtLeast_thenCorrect () {assertThat (SystemUtils.isJavaVersionAtLeast (JavaVersion.JAVA_RECENT)). IsTrue (); }

Er zijn een paar aanvullende hulpprogramma's die de SystemUtils klasse implementeert. We hebben ze weggelaten om de voorbeelden kort te houden.

8. De Lazy Initialization en Builder Classes

Een van de meest aansprekende facetten van Apache Commons Lang 3 is de implementatie van een aantal bekende ontwerppatronen, waaronder de lazy-initialization en builder-patronen.

Laten we bijvoorbeeld zeggen dat we een dure hebben gemaakt Gebruiker class (niet beknopt weergegeven), en de instantiatie ervan willen uitstellen totdat deze echt nodig is.

In dat geval hoeven we alleen maar de geparameteriseerde LazyInitializer abstracte klasse uit te breiden en de initialiseren () methode:

public class UserInitializer breidt LazyInitializer uit {@Override protected User initialize () {return new User ("John", "[email protected]"); }}

Nu, als we ons duur willen krijgen Gebruiker object wanneer het nodig is, noemen we gewoon de Get () van UserInitializer methode:

@Test openbare leegte whenCalledget_thenCorrect () gooit ConcurrentException {UserInitializer userInitializer = nieuwe UserInitializer (); assertThat (userInitializer.get ()). isInstanceOf (User.class); }

De krijgen() method is een implementatie van het dubbelcheck idioom (thread-safe) voor een instantieveld, zoals gespecificeerd in Joshua Bloch's "Effectieve Java", item 71:

privé vluchtige gebruikersinstantie; Gebruiker get () {if (instance == null) {synchronized (this) {if (instance == null) instance = nieuwe gebruiker ("John", "[email protected]"); }}} terugkeerinstantie; }

Bovendien implementeert Apache Commons Lang 3 de klasse HashCodeBuilder, waarmee we hashCode () implementaties door de bouwer te voorzien van verschillende parameters, gebaseerd op een typische vloeiende API:

@Test public void whenCalledtoHashCode_thenCorrect () {int hashcode = nieuwe HashCodeBuilder (17, 37) .append ("John") .append ("[email protected]") .toHashCode (); assertThat (hashcode) .isEqualTo (1269178828); }

We kunnen iets soortgelijks doen met de BasicThreadFactory class en maak daemon-threads met een naamgevingspatroon en een prioriteit:

@Test openbare void whenCalledBuilder_thenCorrect () {BasicThreadFactory factory = nieuwe BasicThreadFactory.Builder () .namingPattern ("workerthread-% d") .daemon (true) .priority (Thread.MAX_PRIORITY) .build (); assertThat (fabriek) .isInstanceOf (BasicThreadFactory.class); }

9. Het ConstructorUtils Klasse

Reflection is een eersteklas burger in Apache Commons Lang 3.

De bibliotheek bevat verschillende reflectieklassen, waardoor we op een reflectieve manier toegang hebben tot klassevelden en methoden en deze kunnen manipuleren.

Laten we bijvoorbeeld zeggen dat we een naïef hebben geïmplementeerd Gebruiker domeinklasse:

openbare klasse Gebruiker {privé Stringnaam; privé String-e-mail; // standard constructors / getters / setters / toString}

Ervan uitgaande dat de geparameteriseerde constructor openbaar, hebben we er gemakkelijk toegang toe met de ConstructorUtils klasse:

@Test openbare leegte whenCalledgetAccessibleConstructor_thenCorrect () {assertThat (ConstructorUtils .getAccessibleConstructor (User.class, String.class, String.class)) .isInstanceOf (Constructor.class); } 

Als alternatief voor standaard klasse-instantiatie via constructors, kunnen we reflectief creëren Gebruiker instanties door gewoon de invokeConstructor () en invokeExactConstructor () methoden:

@Test openbare leegte whenCalledinvokeConstructor_thenCorrect () gooit uitzondering {assertThat (ConstructorUtils.invokeConstructor (User.class, "name", "email")) .isInstanceOf (User.class); } @Test public void whenCalledinvokeExactConstructor_thenCorrect () gooit Uitzondering {String [] args = {"naam", "e-mail"}; Klasse [] parameterTypes = {String.class, String.class}; assertThat (ConstructorUtils.invokeExactConstructor (User.class, args, parameterTypes)) .isInstanceOf (User.class); } 

10. Het FieldUtils Klasse

Evenzo we kunnen de methoden van de FieldUtils klasse voor het reflectief lezen / schrijven van klassevelden.

Laten we aannemen dat we een veld van de Gebruiker klasse, of uiteindelijk een veld dat de klasse erft van een superklasse.

In dat geval kunnen we een beroep doen op de getField () methode:

@Test openbare leegte whenCalledgetField_thenCorrect () {assertThat (FieldUtils.getField (User.class, "name", true) .getName ()) .isEqualTo ("name"); } 

Alternatief, als we een meer beperkende reflectieomvang zouden willen gebruiken, en alleen een veld gedeclareerd krijgen in de Gebruiker klasse, en niet geërfd van een superklasse, zouden we gewoon de getDeclaredField () methode:

@Test openbare leegte whenCalledgetDeclaredFieldForceAccess_thenCorrect () {assertThat (FieldUtils.getDeclaredField (User.class, "name", true) .getName ()) .isEqualTo ("name"); }

Daarnaast kunnen we de getAllFields () methode voor het verkrijgen van het aantal velden van de gereflecteerde klasse, en schrijf een waarde naar een gedeclareerd veld of een veld gedefinieerd in een hiërarchie met de writeField () en writeDeclaredField () methoden:

@Test openbare leegte whenCalledgetAllFields_thenCorrect () {assertThat (FieldUtils.getAllFields (User.class) .length) .isEqualTo (2); } @Test public void whenCalledwriteField_thenCorrect () gooit IllegalAccessException {FieldUtils.writeField (gebruiker, "naam", "Julie", true); assertThat (FieldUtils.readField (gebruiker, "naam", waar)) .isEqualTo ("Julie"); } @Test openbare leegte gegevenFieldUtilsClass_whenCalledwriteDeclaredField_thenCorrect () gooit IllegalAccessException {FieldUtils.writeDeclaredField (gebruiker, "naam", "Julie", true); assertThat (FieldUtils.readField (gebruiker, "naam", waar)) .isEqualTo ("Julie"); }

11. Het MethodUtils Klasse

Op dezelfde manier kunnen we reflectie op klassemethoden gebruiken met de MethodUtils klasse.

In dit geval is de zichtbaarheid van de Gebruiker klasse' getName () methode is openbaar. We hebben er dus toegang toe met de getAccessibleMethod () methode:

@Test openbare leegte whenCalledgetAccessibleMethod_thenCorrect () {assertThat (MethodUtils.getAccessibleMethod (User.class, "getName")) .isInstanceOf (Method.class); } 

Als het gaat om het reflectief aanroepen van methoden, kunnen we de invokeExactMethod () en invokeMethod () methoden:

@Test public void whenCalledinvokeExactMethod_thenCorrect () gooit uitzondering {assertThat (MethodUtils.invokeExactMethod (nieuwe gebruiker ("John", "[email protected]"), "getName")) .isEqualTo ("John"); } @Test public void whenCalledinvokeMethod_thenCorrect () genereert Uitzondering {User user = nieuwe gebruiker ("John", "[email protected]"); Object method = MethodUtils.invokeMethod (gebruiker, true, "setName", "John"); assertThat (user.getName ()). isEqualTo ("John"); }

12. Het MutableObject Klasse

Hoewel onveranderlijkheid een belangrijk kenmerk is van goede objectgeoriënteerde software die we in elk mogelijk geval standaard zouden moeten gebruiken, helaas hebben we soms te maken met veranderlijke objecten.

Bovendien vereist het maken van veranderlijke klassen veel standaardcode, die door de meeste IDE's kan worden gegenereerd via automatisch gegenereerde setters.

Daartoe biedt Apache Commons Lang 3 de MutableObject class, een eenvoudige wrapper-klasse voor het maken van veranderlijke objecten met een minimum aan gedoe:

@BeforeClass openbare statische leegte setUpMutableObject () {mutableObject = nieuw MutableObject ("Oorspronkelijke waarde"); } @Test openbare leegte whenCalledgetValue_thenCorrect () {assertThat (mutableObject.getValue ()). IsInstanceOf (String.class); } @Test public void whenCalledsetValue_thenCorrect () {mutableObject.setValue ("Another value"); assertThat (mutableObject.getValue ()). isEqualTo ("Another value"); } @Test openbare void whenCalledtoString_thenCorrect () {assertThat (mutableObject.toString ()). IsEqualTo ("Another value"); } 

Dit is natuurlijk slechts een voorbeeld van hoe u de MutableObject klasse.

Als vuistregel: we moeten er altijd naar streven om onveranderlijke klassen te creëren, of in het ergste geval alleen het vereiste niveau van veranderlijkheid te bieden.

13. Het MutablePair Klasse

Interessant genoeg biedt Apache Commons Lang 3 sterke ondersteuning voor tuples, in de vorm van paren en triples.

Laten we dus aannemen dat we een veranderlijk paar geordende elementen moeten maken.

In dat geval gebruiken we de MutablePair klasse:

privé statisch MutablePair mutablePair; @BeforeClass openbare statische leegte setUpMutablePairInstance () {mutablePair = nieuw MutablePair ("leftElement", "rightElement"); } @Test openbare leegte whenCalledgetLeft_thenCorrect () {assertThat (mutablePair.getLeft ()). IsEqualTo ("leftElement"); } @Test openbare leegte whenCalledgetRight_thenCorrect () {assertThat (mutablePair.getRight ()). IsEqualTo ("rightElement"); } @Test openbare leegte whenCalledsetLeft_thenCorrect () {mutablePair.setLeft ("newLeftElement"); assertThat (mutablePair.getLeft ()). isEqualTo ("newLeftElement"); } 

Het meest relevante detail dat het vermelden waard is, is de klasse 'schone API'.

Hiermee kunnen we de linker- en rechterobjecten die door het paar zijn verpakt, instellen en openen via de standaard setters / getters.

14. Het Onveranderlijk paar Klasse

Het is niet verwonderlijk dat er ook een onveranderlijke tegenhanger-implementatie is van de MutablePair klasse, genaamd Onveranderlijk paar:

privé statisch ImmutablePair immutablePair = nieuw ImmutablePair ("leftElement", "rightElement"); @Test openbare leegte whenCalledgetLeft_thenCorrect () {assertThat (immutablePair.getLeft ()). IsEqualTo ("leftElement"); } @Test openbare leegte whenCalledgetRight_thenCorrect () {assertThat (immutablePair.getRight ()). IsEqualTo ("rightElement"); } @Test openbare leegte whenCalledof_thenCorrect () {assertThat (ImmutablePair.of ("leftElement", "rightElement")) .isInstanceOf (ImmutablePair.class); } @Test (verwacht = UnsupportedOperationException.class) public void whenCalledSetValue_thenThrowUnsupportedOperationException () {immutablePair.setValue ("newValue"); } 

Zoals we kunnen verwachten van een onveranderlijke klasse, kan elke poging om de interne status van het paar te veranderen via de setValue () methode zal resulteren in het gooien van een UnsupportedOperationException uitzondering.

15. De Verdrievoudigen Klasse

De laatste utility-klasse die hier zal kijken, is Verdrievoudigen.

Omdat de klas abstract is, kunnen we creëren Verdrievoudigen instanties met behulp van de van() statische fabrieksmethode:

@BeforeClass openbare statische leegte setUpTripleInstance () {triple = Triple.of ("leftElement", "middleElement", "rightElement"); } @Test openbare leegte whenCalledgetLeft_thenCorrect () {assertThat (triple.getLeft ()). IsEqualTo ("leftElement"); } @Test openbare leegte whenCalledgetMiddle_thenCorrect () {assertThat (triple.getMiddle ()). IsEqualTo ("middleElement"); } @Test openbare leegte whenCalledgetRight_thenCorrect () {assertThat (triple.getRight ()). IsEqualTo ("rightElement"); }

Er zijn ook concrete implementaties voor zowel veranderlijke als onveranderlijke triples, via de MutableTriple en Onveranderlijk Triple klassen.

We kunnen hun instanties maken via geparametriseerde constructors, in plaats van met een statische fabrieksmethode.

In dit geval slaan we ze gewoon over, omdat hun API's erg lijken op die van de MutablePair en Onveranderlijk paar klassen.

16. Conclusie

In deze tutorial hebben we een aantal van de handigste utility-klassen die Apache Commons Lang 3 biedt, grondig bekeken uit de plank .

De bibliotheek implementeert vele andere hulpprogramma-klassen die het bekijken waard zijn. Hier hebben we zojuist de meest bruikbare laten zien, gebaseerd op een behoorlijk eigenwijs criterium.

Raadpleeg de officiële Javadocs voor de volledige bibliotheek-API.

Zoals gewoonlijk zijn alle codevoorbeelden die in deze tutorial worden getoond, beschikbaar op GitHub.