Generiske konstruktører i Java

1. Oversikt

Vi har tidligere diskutert det grunnleggende om Java Generics. I denne opplæringen tar vi en titt på Generic Constructors i Java.

En generisk konstruktør er en konstruktør som har minst en parameter av en generisk type.

Vi får se at generiske konstruktører ikke trenger å være i en generisk klasse, og ikke alle konstruktører i en generisk klasse må være generiske.

2. Ikke-generisk klasse

Først har vi en enkel klasse Inngang, som ikke er en generisk klasse:

offentlig klasse Oppføring {private String data; privat int rang; }

I denne klassen legger vi til to konstruktører: en grunnleggende konstruktør med to parametere og en generisk konstruktør.

2.1. Grunnleggende konstruktør

Den første Inngang constructor er en enkel konstruktør med to parametere:

offentlig oppføring (String data, int rang) {this.data = data; this.rank = rang; }

La oss nå bruke denne grunnleggende konstruktøren til å lage en Inngang gjenstand:

@Test public void givenNonGenericConstructor_whenCreateNonGenericEntry_thenOK () {Entry entry = new Entry ("sample", 1); assertEquals ("sample", entry.getData ()); assertEquals (1, entry.getRank ()); }

2.2. Generisk konstruktør

Deretter er vår andre konstruktør en generisk konstruktør:

public Entry (E element) {this.data = element.toString (); this.rank = element.getRank (); }

Selv om Inngang klasse er ikke generisk, den har en generisk konstruktør, siden den har en parameter element av typen E.

Den generiske typen E er avgrenset og skal implementere begge deler Rangering og Serialiserbar grensesnitt.

La oss ta en titt på Rangering grensesnitt, som har en metode:

offentlig grensesnitt Rangering {public int getRank (); }

Anta at vi har en klasse Produkt som implementerer Rangering grensesnitt:

offentlig klasse Produktredskaper Rangable, Serializable {private String name; privat dobbel pris; private int salg; offentlig produkt (strengnavn, dobbel pris) {this.name = navn; dette.pris = pris; } @ Override public int getRank () {retur salg; }}

Vi kan da bruke den generiske konstruktøren til å lage Inngang gjenstander som bruker en Produkt:

@Test offentlig ugyldighet gittGenericConstructor_whenCreateNonGenericEntry_thenOK () {Produktprodukt = nytt produkt ("melk", 2.5); product.setSales (30); Oppføringsoppføring = ny oppføring (produkt); assertEquals (product.toString (), entry.getData ()); assertEquals (30, entry.getRank ()); }

3. Generisk klasse

Deretter tar vi en titt på en generisk klasse som heter GenericEntry:

offentlig klasse GenericEntry {private T-data; privat int rang; }

Vi legger til de samme to typene konstruktører som forrige avsnitt i denne klassen.

3.1. Grunnleggende konstruktør

La oss først skrive en enkel, ikke-generisk konstruktør for vår GenericEntry klasse:

offentlig GenericEntry (int rang) {this.rank = rang; }

Selv om GenericEntry er en generisk klasse, dette er en enkel konstruktør som ikke har en parameter av en generisk type.

Nå kan vi bruke denne konstruktøren til å lage en GenericEntry:

@Test public void givenNonGenericConstructor_whenCreateGenericEntry_thenOK () {GenericEntry entry = new GenericEntry (1); assertNull (entry.getData ()); assertEquals (1, entry.getRank ()); }

3.2. Generisk konstruktør

La oss deretter legge til den andre konstruktøren i klassen vår:

offentlig GenericEntry (T-data, int-rangering) {this.data = data; this.rank = rang; }

Dette er en generisk konstruktør, da den har en data parameter av den generiske typen T. Merk at vi ikke trenger å legge til i konstruktørerklæringen, da den implisitt er der.

La oss nå teste den generiske konstruktøren vår:

@Test offentlig ugyldighet gittGenericConstructor_whenCreateGenericEntry_thenOK () {GenericEntry entry = new GenericEntry ("sample", 1); assertEquals ("sample", entry.getData ()); assertEquals (1, entry.getRank ()); }

4. Generisk konstruktør med forskjellig type

I vår generiske klasse kan vi også ha en konstruktør med en generisk type som er forskjellig fra klassens generiske type:

public GenericEntry (E element) {this.data = (T) element; this.rank = element.getRank (); }

Dette GenericEntry konstruktøren har en parameter element med type E, som er forskjellig fra T type. La oss se det i aksjon:

@Test offentlig ugyldighet gittGenericConstructorWithDifferentType_whenCreateGenericEntry_thenOK () {Produkt produkt = nytt produkt ("melk", 2.5); product.setSales (30); GenericEntry entry = new GenericEntry (product); assertEquals (produkt, entry.getData ()); assertEquals (30, entry.getRank ()); }

Noter det:

  • I vårt eksempel brukte vi Produkt (E) for å lage en GenericEntry av typen Serialiserbar (T)
  • Vi kan bare bruke denne konstruktøren når parameteren av typen E kan støpes til T

5. Flere generiske typer

Deretter har vi generisk klasse MapEntry med to generiske typer:

offentlig klasse MapEntry {privat K-nøkkel; privat V-verdi; offentlig MapEntry (K-tast, V-verdi) {this.key = key; this.value = verdi; }}

MapEntry har en generisk konstruktør med to parametere, hver av en annen type. La oss bruke den i en enkel enhetstest:

@Test public void givenGenericConstructor_whenCreateGenericEntryWithTwoTypes_thenOK () {MapEntry entry = new MapEntry ("sample", 1); assertEquals ("sample", entry.getKey ()); assertEquals (1, entry.getValue (). intValue ()); }

6. Jokertegn

Til slutt kan vi bruke jokertegn i en generisk konstruktør:

public GenericEntry (Valgfritt valgfritt) {if (optional.isPresent ()) {this.data = (T) optional.get (); this.rank = optional.get (). getRank (); }}

Her brukte vi jokertegn i dette GenericEntry konstruktør å binde Valgfri type:

@Test offentlig ugyldighet gittGenericConstructorWithWildCard_whenCreateGenericEntry_thenOK () {Produkt produkt = nytt produkt ("melk", 2.5); product.setSales (30); Valgfritt valgfritt = Valgfritt. Av (produkt); GenericEntry entry = new GenericEntry (valgfritt); assertEquals (produkt, entry.getData ()); assertEquals (30, entry.getRank ()); }

Merk at vi skal kunne kaste den valgfrie parametertypen (i vårt tilfelle Produkt) til GenericEntry type (i vårt tilfelle, Serialiserbar).

7. Konklusjon

I denne artikkelen lærte vi hvordan vi kunne definere og bruke generiske konstruktører i både generiske og ikke-generiske klasser.

Hele kildekoden finner du på GitHub.