Skriv sletning i Java forklaret

1. Oversigt

I denne hurtige artikel vil vi diskutere det grundlæggende i en vigtig mekanisme i Javas generika kendt som type sletning.

2. Hvad er type sletning?

Type sletning kan forklares som processen med kun at håndhæve typebegrænsninger på kompileringstidspunktet og kassering af elementtypeoplysningerne under kørsel.

For eksempel:

public static boolean containElement (E [] elements, E element) {for (E e: elements) {if (e.equals (element)) {return true; }} returner falsk; }

Compileren erstatter den ubundne type E med en faktisk type Objekt:

public static boolean containElement (Object [] elements, Object element) {for (Object e: elements) {if (e.equals (element)) {return true; }} returner falsk; }

Derfor sørger kompilatoren for typesikkerhed for vores kode og forhindrer runtime-fejl.

3. Typer af sletning af typer

Type sletning kan forekomme på klasse (eller variabel) og metodeniveau.

3.1. Klassetype sletning

På klasseniveau kasserer kompilatoren typeparametrene på klassen og erstatter dem med dens første grænse, eller Objekt hvis typeparameteren er ubundet.

Lad os implementere en Stak ved hjælp af en matrix:

offentlig klasse Stak {privat E [] stackContent; offentlig stak (int kapacitet) {this.stackContent = (E []) nyt objekt [kapacitet]; } public void push (E data) {// ..} public E pop () {// ..}}

Efter kompilering erstatter compileren parameteren for ikke-bundet type E med Objekt:

offentlig klasse Stak {privat Objekt [] stackContent; offentlig stak (int kapacitet) {this.stackContent = (Objekt []) nyt Objekt [kapacitet]; } public void push (Object data) {// ..} public Object pop () {// ..}}

I et tilfælde hvor typeparameteren E er bundet:

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

Compileren erstatter parameteren for bundet type E med den første bundne klasse, Sammenlignelig I dette tilfælde:

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 Sletning

Til sletning af metodeniveautype gemmes metodens type-parameter ikke, men konverteres snarere til dens overordnede type Objekt hvis det er ubundet, eller det er første bundet klasse, når det er bundet.

Lad os overveje en metode til at vise indholdet af et givet array:

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

Efter kompilering erstatter compileren typeparameteren E med Objekt:

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

For en bundet metodetypeparameter:

offentlig statisk  ugyldig 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 sager

Engang under typesletningsprocessen opretter kompilatoren en syntetisk metode til at differentiere lignende metoder. Disse kan komme fra metodesignaturer, der udvider den samme første bundne klasse.

Lad os oprette en ny klasse, der udvider vores tidligere implementering af Stak. Bemærk, at dette refererer til Stak klasse, vi oprettede i afsnit 3.1, og ikke java.util.Stack.

offentlig klasse IntegerStack udvider Stack {public IntegerStack (int capacity) {super (capacity); } public void push (Heltalsværdi) {super.push (værdi); }}

Lad os nu se på følgende kode:

IntegerStack integerStack = ny IntegerStack (5); Stack stack = integerStack; stack.push ("Hej"); Heltalsdata = integerStack.pop ();

Efter sletning af typen har vi:

IntegerStack integerStack = ny IntegerStack (5); Stack stack = (IntegerStack) integerStack; stack.push ("Hej"); Heltalsdata = (String) integerStack.pop ();

Læg mærke til, hvordan vi kan skubbe en String på den IntegerStack - fordi IntegerStack arvet skub (Objekt) fra forældreklassen Stak. Dette er naturligvis forkert - da det burde være et helt tal siden da integerStack er en Stak type.

Så ikke overraskende et forsøg på at pop -en Snor og tildele til en Heltal forårsager en ClassCastException fra en rollebesætning indsat under skubbe af kompilatoren.

4.1. Brometoder

For at løse kanttilstanden ovenfor opretter kompilatoren undertiden en brometode. Dette er en syntetisk metode, der er oprettet af Java-kompilatoren under kompilering af en klasse eller grænseflade, der udvider en parametreret klasse eller implementerer en parametreret interface, hvor metodesignaturer kan være lidt forskellige eller tvetydige.

I vores eksempel ovenfor bevarer Java-kompilatoren polymorfisme af generiske typer efter sletning ved at sikre, at der ikke er nogen mismatch mellem metodesignaturer mellem IntegerStack'S skub (heltal) metode og Stak'S skub (Objekt) metode.

Derfor opretter compileren en brometode her:

public class IntegerStack udvider Stack {// Bridge-metoden genereret af compileren public void push (Object value) {push ((Integer) value); } public void push (Integer value) {super.push (value); }}

Følgelig, Stak klassens skubbe metode efter type sletning, delegerer til originalen skubbe metode til IntegerStack klasse.

5. Konklusion

I denne vejledning har vi diskuteret begrebet type sletning med eksempler i typeparametervariabler og -metoder.

Du kan læse mere om disse begreber:

  • Java-sprogspecifikation: Skriv sletning
  • Grundlæggende om Java Generics

Som altid er kildekoden, der ledsager denne artikel, tilgængelig på GitHub.