Skriv sletting i Java forklart

1. Oversikt

I denne raske artikkelen vil vi diskutere det grunnleggende om en viktig mekanisme i Java's generikk, kjent som type sletting.

2. Hva er type sletting?

Type sletting kan forklares som prosessen med å håndheve typebegrensninger bare på kompileringstidspunktet og forkaste informasjonen om elementtypen ved kjøretid.

For eksempel:

offentlig statisk boolsk inneholderElement (E [] -elementer, E-element) {for (E e: elementer) {if (e.equals (element)) {return true; }} returner falsk; }

Kompilatoren erstatter den ubundne typen E med en faktisk type Gjenstand:

offentlig statisk boolsk inneholderElement (Object [] -elementer, Object-element) {for (Object e: elements) {if (e.equals (element)) {return true; }} returner falsk; }

Derfor sørger kompilatoren for typesikkerhet for koden vår og forhindrer kjøretidsfeil.

3. Typer sletting av typer

Type sletting kan forekomme på klasse (eller variabel) og metodenivå.

3.1. Klassetype Sletting

På klassenivå forkaster kompilatoren typeparametrene på klassen og erstatter dem med sin første innbinding, eller Gjenstand hvis typeparameteren er ubundet.

La oss implementere en Stable ved hjelp av en matrise:

offentlig klasse Stack {private E [] stackContent; public Stack (int capacity) {this.stackContent = (E []) new Object [capacity]; } public void push (E data) {// ..} public E pop () {// ..}}

Ved kompilering erstatter kompilatoren parameteren for ubundet type E med Gjenstand:

offentlig klasse Stack {private Object [] stackContent; public Stack (int capacity) {this.stackContent = (Object []) new Object [capacity]; } public void push (Object data) {// ..} public Object pop () {// ..}}

I et tilfelle der typeparameteren E er bundet:

offentlig klasse BoundStack {private E [] stackContent; public BoundStack (int capacity) {this.stackContent = (E []) new Object [capacity]; } public void push (E data) {// ..} public E pop () {// ..}}

Kompilatoren erstatter parameteren for bundet type E med første bundet klasse, Sammenlignelig i dette tilfellet:

offentlig klasse BoundStack {private Comparable [] stackContent; public BoundStack (int capacity) {this.stackContent = (Comparable []) new Object [capacity]; } public void push (Comparable data) {// ..} public Comparable pop () {// ..}}

3.2. Metode Type Sletting

For sletting av metodenivå lagres ikke metodens typeparameter, men konverteres til den overordnede typen Gjenstand hvis det er ubundet eller det er første bundet klasse når det er bundet.

La oss vurdere en metode for å vise innholdet i et gitt utvalg:

public static void printArray (E [] array) {for (E element: array) {System.out.printf ("% s", element); }}

Ved kompilering erstatter kompilatoren typeparameteren E med Gjenstand:

public static void printArray (Object [] array) {for (Object element: array) {System.out.printf ("% s", element); }}

For en innbundet metodetypeparameter:

offentlig statisk  void printArray (E [] array) {for (E element: array) {System.out.printf ("% s", element); }}

Vi har typeparameteren E slettet og erstattet med Sammenlignelig:

public static void printArray (Comparable [] array) {for (Comparable element: array) {System.out.printf ("% s", element); }}

4. Edge Cases

En gang i løpet av typesletteprosessen lager kompilatoren en syntetisk metode for å skille lignende metoder. Disse kan komme fra metodesignaturer som utvider den samme første bundne klassen.

La oss lage en ny klasse som utvider vår forrige implementering av Stable. Vær oppmerksom på at dette refererer til Stable klasse vi opprettet i avsnitt 3.1, og ikke java.util.Stack.

offentlig klasse IntegerStack utvider Stack {public IntegerStack (int kapasitet) {super (kapasitet); } public void push (Integer value) {super.push (value); }}

La oss nå se på følgende kode:

IntegerStack integerStack = ny IntegerStack (5); Stack stack = integerStack; stack.push ("Hei"); Heltalldata = integerStack.pop ();

Etter sletting av typen har vi:

IntegerStack integerStack = ny IntegerStack (5); Stack stack = (IntegerStack) integerStack; stack.push ("Hei"); Heltalldata = (String) integerStack.pop ();

Legg merke til hvordan vi kan presse a StringIntegerStack - fordi IntegerStack arvet trykk (Objekt) fra foreldreklassen Stable. Dette er selvfølgelig feil - siden det burde være et heltall siden integerStack er en Stable type.

Så ikke overraskende et forsøk på pop en String og tilordne en Heltall forårsaker en ClassCastException fra en rollebesetning satt inn under trykk av kompilatoren.

4.1. Brometoder

For å løse kantsaken ovenfor, lager kompilatoren noen ganger en brometode. Dette er en syntetisk metode opprettet av Java-kompilatoren mens du kompilerer en klasse eller et grensesnitt som utvider en parameterisert klasse eller implementerer et parameterisert grensesnitt der metodesignaturer kan være litt forskjellige eller tvetydige.

I vårt eksempel ovenfor bevarer Java-kompilatoren polymorfisme av generiske typer etter sletting ved å sikre at det ikke er noen samsvar mellom metodesignaturen mellom IntegerStack‘S trykk (Heltall) metode og Stable‘S trykk (Objekt) metode.

Derfor lager kompilatoren en brometode her:

offentlig klasse IntegerStack utvider Stack {// Bridge-metoden generert av kompilatoren public void push (Object value) {push ((Integer) value); } public void push (Integer value) {super.push (value); }}

Følgelig Stable klasse trykk metode etter type sletting, delegerer til originalen trykk Metode av IntegerStack klasse.

5. Konklusjon

I denne veiledningen har vi diskutert begrepet type sletting med eksempler i type parametervariabler og metoder.

Du kan lese mer om disse konseptene:

  • Java språkspesifikasjon: Skriv inn Erasure
  • Grunnleggende om Java Generics

Som alltid er kildekoden som følger med denne artikkelen tilgjengelig på GitHub.


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