Java >> Java tutorial >  >> Tag >> static

Use Cases til statiske metoder i Java

1. Oversigt

Statiske metoder er fælles for de fleste objektorienterede programmeringssprog, inklusive Java. Det, der adskiller statisk fra instansmetoder, er, at de ikke har noget objekt, der ejer dem. I stedet er statiske metoder defineret på klasseniveau og kan bruges uden at oprette forekomster .

I denne tutorial vil vi se på definitionen af ​​statiske metoder i Java, såvel som deres begrænsninger. Derefter vil vi se på almindelige use cases for brug af statiske metoder og anbefale, hvornår det giver mening at anvende dem i vores kode.

Til sidst vil vi se, hvordan man tester statiske metoder, og hvordan man håner dem.

2. Statiske metoder

Forekomstmetoder løses polymorf baseret på objektets runtime-type. På den anden side løses statiske metoder på kompileringstidspunktet baseret på den klasse, de er defineret i.

2.1. Klasseniveau

En statisk metode i Java er en del af klassedefinitionen. Vi kan definere en statisk metode ved at tilføje den statiske nøgleord til en metode:

private static int counter = 0;

public static int incrementCounter() {
    return ++counter;
}

public static int getCounterValue() {
    return counter;
}

For at få adgang til statiske metoder bruger vi klassenavnet efterfulgt af en prik og navnet på metoden :

int oldValue = StaticCounter.getCounterValue();
int newValue = StaticCounter.incrementCounter();
assertThat(newValue).isEqualTo(oldValue + 1);

Vi skal bemærke, at denne statiske metode har adgang til den statiske tilstand for StaticCounter klasse. Statiske metoder er ofte statsløse, men de kan arbejde med data på klasseniveau som en del af forskellige teknikker, herunder singleton-mønsteret.

Selvom det også er muligt at referere til statiske metoder ved hjælp af objekter, markeres dette antimønster ofte som en fejl af værktøjer som f.eks. Sonar.

2.2. Begrænsninger

Da statiske metoder ikke fungerer på instansmedlemmer , der er et par begrænsninger, vi bør være opmærksomme på:

  • En statisk metode kan ikke referere direkte til instansmedlemsvariabler
  • En statisk metode kan ikke kalde en instansmetode direkte
  • Underklasser kan ikke tilsidesætte statiske metoder
  • Vi kan ikke bruge søgeord dette og super i en statisk metode

Hvert af ovenstående resulterer i en kompileringsfejl. Vi skal også bemærke, at hvis vi erklærer en statisk metode med samme navn i en underklasse, tilsidesætter den ikke, men skjuler i stedet basisklassemetoden.

3. Use Cases

Lad os nu se på almindelige brugstilfælde, når det giver mening at anvende statiske metoder i vores Java-kode.

3.1. Standardadfærd

Det giver mening at bruge statiske metoder, når vi udvikler metoder med standardadfærd der opererer på deres input-argumenter.

strengen operationer fra Apache StringUtils er et godt eksempel på dette:

String str = StringUtils.capitalize("baeldung");
assertThat(str).isEqualTo("Baeldung");

Et andet godt eksempel er Samlingerne klasse, da den indeholder almindelige metoder, der fungerer på forskellige samlinger:

List<String> list = Arrays.asList("1", "2", "3");
Collections.reverse(list);
assertThat(list).containsExactly("3", "2", "1");

3.2. Genbrug på tværs af forekomster

En gyldig grund til at bruge statiske metoder er, når vi genbruger standardadfærd på tværs af forekomster af forskellige klasser .

For eksempel bruger vi almindeligvis Java samlinger og Apache StringUtils i vores domæne og business classes:

Da disse funktioner ikke har deres egen tilstand og ikke er bundet til en bestemt del af vores forretningslogik, giver det mening at opbevare dem i et modul, hvor de kan deles.

3.3. Skifter ikke tilstand

Da statiske metoder ikke kan referere til instansmedlemsvariabler, er de et godt valg til metoder, der ikke kræver nogen objekttilstandsmanipulation.

Når vi bruger statiske metoder til operationer, hvor staten ikke styres, så er metodekald mere praktisk. Den, der ringer, kan kalde metoden direkte uden at skulle oprette forekomster.

Når vi deler tilstand med alle forekomster af klassen, som i tilfælde af en statisk tæller, så bør metoder, der fungerer på denne tilstand, være statiske. Administration af en global tilstand kan være en kilde til fejl, så Sonar vil rapportere et kritisk problem, når instansmetoder skriver direkte til statiske felter.

3.4. Rene funktioner

En funktion kaldes ren, hvis dens returværdi kun afhænger af de beståede inputparametre . Rene funktioner henter alle data fra deres parametre og beregner noget ud fra disse data.

Rene funktioner fungerer ikke på nogen instans eller statiske variable. Derfor bør udførelse af en ren funktion heller ikke have nogen bivirkninger.

Da statiske metoder ikke tillader tilsidesættelse og reference til instansvariabler, er de et godt valg til implementering af rene funktioner i Java.

4. Hjælpeklasser

Da Java ikke har en bestemt type afsat til at rumme et sæt funktioner, opretter vi ofte en hjælpeklasse. Hjælpeklasser giver et hjem til rene statiske funktioner . I stedet for at skrive den samme logik igen og igen, kan vi samle rene funktioner, som vi genbruger gennem hele projektet.

En hjælpeklasse i Java er en statsløs klasse, som vi aldrig bør instansiere. Derfor anbefales det at erklære det endeligt , så det kan ikke underklassificeres (hvilket ikke ville tilføje værdi). For at forhindre nogen i at forsøge at instansiere det, kan vi tilføje en privat konstruktør:

public final class CustomStringUtils {

    private CustomStringUtils() {
    }

    public static boolean isEmpty(CharSequence cs) { 
        return cs == null || cs.length() == 0; 
    }
}

Vi skal bemærke, at alle metoder, vi sætter i værktøjsklassen, skal være statiske .

5. Test

Lad os tjekke, hvordan vi kan enhedsteste og håne statiske metoder i Java.

5.1. Enhedstest

Enhedstest af veldesignede, rene statiske metoder med JUnit er ret simpelt. Vi kan bruge klassenavnet til at kalde vores statiske metode og videregive nogle testparametre til den.

Vores enhed, der testes, vil beregne resultatet ud fra dens inputparametre. Derfor kan vi fremsætte påstande om resultatet og teste for forskellige input-output kombinationer :

@Test
void givenNonEmptyString_whenIsEmptyMethodIsCalled_thenFalseIsReturned() {
    boolean empty = CustomStringUtils.isEmpty("baeldung");
    assertThat(empty).isFalse();
}

5.2. Hånende

Det meste af tiden behøver vi ikke at håne statiske metoder, og vi kan simpelthen bruge den rigtige funktionsimplementering i vores test. Behovet for at håne statiske metoder antyder typisk et kodedesignproblem.

Hvis vi skal, så kan vi håne statiske funktioner ved hjælp af Mockito. Vi bliver dog nødt til at tilføje en ekstra mockito-inline afhængighed af vores pom.xml:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.8.0</version>
    <scope>test</scope>
</dependency>

Nu kan vi bruge Mockito.mockStatic  metode til at håne påkaldelser til statiske metodekald:

try (MockedStatic<StringUtils> utilities = Mockito.mockStatic(StringUtils.class)) {
    utilities.when(() -> StringUtils.capitalize("karoq")).thenReturn("Karoq");

    Car car1 = new Car(1, "karoq");
    assertThat(car1.getModelCapitalized()).isEqualTo("Karoq");
}

6. Konklusion

I denne artikel, vi udforsket almindelige use cases for brug af statiske metoder i vores Java-kode. Vi lærte definitionen af ​​statiske metoder i Java, såvel som deres begrænsninger.

Vi undersøgte også, hvornår det giver mening at bruge statiske metoder i vores kode. Vi så, at statiske metoder er et godt valg til rene funktioner med standardadfærd, der bliver genbrugt på tværs af instanser, men som ikke ændrer deres tilstand. Til sidst så vi på, hvordan man tester og håner statiske metoder.

Som altid er den komplette kildekode tilgængelig på GitHub.


Java tag