CodeGym /Java-blogg /Tilfeldig /Utvidelse og innsnevring av referansetyper
John Squirrels
Nivå
San Francisco

Utvidelse og innsnevring av referansetyper

Publisert i gruppen
Hei! I en tidligere leksjon diskuterte vi støping av primitive typer. La oss kort huske hva som ble diskutert. Utvidelse og innsnevring av referansetyper - 1Vi så for oss primitive typer (i dette tilfellet numeriske typer) som hekkende dukker som varierer i størrelse i henhold til hvor mye minne de opptar. Som du vil huske, er det enkelt å sette en mindre dukke i en større, både i det virkelige liv og i Java-programmering.

public class Main {
   public static void main(String[] args) {
       int bigNumber = 10000000;
       short smallNumber = (short) bigNumber;
       System.out.println(smallNumber);
   }
}
Dette er et eksempel på automatisk konvertering eller utvidelse . Det skjer av seg selv, så du trenger ikke skrive tilleggskode. Til slutt gjør vi ikke noe uvanlig: vi legger bare en mindre dukke inn i en større dukke. Det er en annen sak om vi prøver å gjøre det motsatte og putter en større russedukke inn i en mindre dukke. Du kan ikke gjøre det i det virkelige liv, men i programmering kan du det. Men det er en nyanse. Hvis vi prøver å sette en intinn i en shortvariabel, går det ikke så greit for oss. Tross alt shortinneholder variabelen bare 16 biter med informasjon, men en intopptar 32 biter! Som et resultat blir den beståtte verdien forvrengt. Kompilatoren vil gi oss en feil (' Dude, du gjør noe mistenkelig!'). Men hvis vi eksplisitt angir typen vi konverterer verdien vår til, vil den gå videre og utføre operasjonen.

public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Det er akkurat det vi gjorde i eksemplet ovenfor. Operasjonen ble utført, men fordi shortvariabelen bare kan romme 16 av de 32 bytene, blir sluttverdien forvrengt og vi får tallet -27008 . En slik operasjon kalles en eksplisitt konvertering, eller innsnevring .

Eksempler på utvidelse og innsnevring av referansetyper

La oss nå snakke om de samme operatorene som ikke brukes på primitive typer, men på objekter og referansevariabler ! Hvordan fungerer dette i Java? Det er faktisk ganske enkelt. Det er gjenstander som ikke er relatert. Det ville være logisk å anta at de ikke kan konverteres til hverandre, verken eksplisitt eller automatisk:

public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Dog(); // Error!

   }

}
Her får vi selvfølgelig en feil. Klassene Catog Doger ikke relatert til hverandre, og vi har ikke skrevet en 'konverter' for å flytte fra den ene til den andre. Det er fornuftig at vi ikke kan gjøre dette: kompilatoren har ingen anelse om hvordan man konverterer disse objektene fra en type til en annen. Hvis gjenstandene er relatert, vel, det er en annen sak! Relatert hvordan? Fremfor alt gjennom arv. La oss prøve å bruke arv til å lage et lite system med klasser. Vi vil ha en felles klasse for å representere dyr:

public class Animal {

   public void introduce() {

       System.out.println("I'm Animal");
   }
}
Alle vet at dyr kan være tamme (kjæledyr) eller ville:

public class WildAnimal extends Animal {

   public void introduce() {

       System.out.println("I'm WildAnimal");
   }
}

public class Pet extends Animal {

   public void introduce() {

       System.out.println("I'm Pet");
   }
}
Ta for eksempel hjørnetenner - vi har tamhunder og coyoter:

public class Dog extends Pet {

   public void introduce() {

       System.out.println("I'm Dog");
   }
}



public class Coyote extends WildAnimal {

   public void introduce() {

       System.out.println ("I'm Coyote");
   }
}
Vi valgte spesifikt de mest grunnleggende klassene for å gjøre dem lettere å forstå. Vi trenger egentlig ingen felt, og én metode er nok. La oss prøve å kjøre denne koden:

public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Hva tror du vil vises på konsollen? Vil introducemetoden til Petklassen eller Animalklassen bli påberopt? Prøv å begrunne svaret ditt før du fortsetter å lese. Og her er resultatet! Jeg er Pet Hvorfor fikk vi det? Det hele er enkelt. Vi har en overordnet variabel og et etterkommerobjekt. Ved å skrive,

Animal animal = new Pet();
vi utvidet en Petreferanse og tilordnet den til en Animalvariabel. Som med primitive typer, utvides referansetyper automatisk i Java. Du trenger ikke skrive tilleggskode for å få det til. Nå har vi et etterkommerobjekt tildelt en overordnet referanse. Som et resultat ser vi at metodekallet gjøres på descendant-klassen. Hvis du fortsatt ikke helt forstår hvorfor denne koden fungerer, kan du skrive den om på vanlig språk:

Animal animal = new DomesticatedAnimal();
Det er ikke noe problem med dette, ikke sant? Tenk deg at dette er det virkelige liv, og referansen er ganske enkelt en papiretikett med 'Animal' skrevet på. Hvis du tar det stykket papir og fester det til halsbåndet til et kjæledyr, vil alt være riktig. Tross alt er ethvert kjæledyr et dyr! Den omvendte prosessen – å flytte nedover arvetreet til etterkommere – blir smalere:

public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Som du kan se, angir vi her tydelig hvilken klasse vi ønsker å konvertere objektet vårt til. Vi hadde tidligere en WildAnimalvariabel, og nå har vi en Coyote, som er lavere på arvetreet. Det er fornuftig at uten en eksplisitt indikasjon vil ikke kompilatoren tillate en slik operasjon, men hvis vi angir typen i parentes, fungerer alt. Utvidelse og innsnevring av referansetyper - 2Tenk på et annet mer interessant eksempel:

public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal(); // Error!
   }
}
Kompilatoren genererer en feil! Men hvorfor? Fordi du prøver å tilordne et overordnet objekt til en etterkommerreferanse. Med andre ord, du prøver å gjøre noe som dette:

DomesticatedAnimal domesticatedAnimal = new Animal();
Vel, kanskje alt vil fungere hvis vi eksplisitt spesifiserer typen vi prøver å konvertere til? Det fungerte med tall — la oss prøve det! :)

public class Main {

   public static void main(String[] args) {

       Pet pet = (Pet) new Animal();
   }
}
Unntak i tråden "hoved" java.lang.ClassCastException: Dyr kan ikke kastes til Pet Feil! Kompilatoren kjeftet ikke på oss denne gangen, men vi endte opp med et unntak. Vi vet allerede årsaken: vi prøver å tilordne et overordnet objekt til en etterkommerreferanse. Men hvorfor akkurat kan du ikke gjøre det? Fordi ikke alle dyr er tamme dyr. Du opprettet et Animalobjekt og prøver å tilordne det til en Petvariabel. En coyote er også en Animal, men den er ikke en Pet. Med andre ord, når du skriver

Pet pet = (Pet) new Animal();
new Animal()kan representere et hvilket som helst dyr, ikke nødvendigvis et kjæledyr! Naturligvis er variabelen din Pet petbare egnet for oppbevaring av kjæledyr (og deres etterkommere) og ikke alle typer dyr. Det er derfor et spesielt Java-unntak, ClassCastException, ble opprettet for tilfeller der det oppstår en feil under casting av klasser. La oss gå gjennom det igjen for å gjøre ting klarere. En overordnet referanse kan peke til forekomster av en etterkommerklasse:

public class Main {

   public static void main(String[] args) {

       Pet pet = new Pet();
       Animal animal = pet;

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
For eksempel, her har vi ingen problemer. Vi har et Petobjekt referert til av en Petvariabel. Senere pekte en Animalreferanse på det samme objektet. Etter det konverterer vi animaltil en Pet. Forresten, hvorfor fungerte det for oss? Sist gang fikk vi et unntak! For denne gangen er vårt originale objekt en Pet!

Pet pet = new Pet();
Men i det siste eksemplet var det et Animalobjekt:

Pet pet = (Pet) new Animal();
Du kan ikke tilordne et forfedreobjekt til en etterkommervariabel. Du kan gjøre det motsatte.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION