1. Typecasten

Variabelen die referentietypen (klassen) opslaan, kunnen ook worden geconverteerd naar verschillende typen. Maar dit werkt alleen binnen een enkele typehiërarchie. Laten we naar een eenvoudig voorbeeld kijken. Stel dat we de volgende klassenhiërarchie hebben, waarin de klassen eronder de klassen erboven erven.

Typecasting

Typecasting van zowel referentietypen als primitieve typen wordt ook gecategoriseerd als verbreding of versmalling.

We zien dat de klasse Cat de klasse Pet overerft, en de klasse Pet op zijn beurt de klasse Animal.

Als we code als volgt schrijven:

Animal kitten = new Cat();

Dit is een conversie van het verbredende type . Het wordt ook wel een impliciete cast genoemd. We hebben de cat- referentie verbreed zodat deze nu verwijst naar een Cat- object. Met een dergelijke typeconversie kunnen we de kittenreferentie niet gebruiken om methoden aan te roepen die aanwezig zijn in de Cat- klasse maar afwezig zijn in de Animal- klasse.

Een vernauwende conversie (of expliciete cast) gebeurt in de tegenovergestelde richting:

Cat cat = (Cat) kitten;

We hebben expliciet aangegeven dat we de referentie die is opgeslagen in de variabele kitten (waarvan het type Animal is) willen casten naar het type Cat .



2. Het type van een object controleren

Maar je moet hier heel voorzichtig zijn. Als je dit doet:

Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;

De compiler staat deze code toe, maar er treedt een fout op wanneer het programma wordt uitgevoerd! De JVM genereert een uitzondering:

Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf

Verwijzingen naar een Cat- object kunnen alleen worden opgeslagen in variabelen waarvan het type een voorouder is van de Cat-klasse: Pet, Animal of Object.

Waarom is dat?

Het relevante punt hier is dat een objectreferentie wordt gebruikt om te verwijzen naar de methoden en variabelen van dat object . En er zullen geen problemen zijn als we een Animal-variabele gebruiken om een ​​verwijzing naar een Cat-object op te slaan: het Cat-type heeft altijd variabelen en methoden van het Animal-type — het heeft ze geërfd!

Maar als de JVM ons toestaat een verwijzing naar een Cat-object op te slaan in een Wolf-variabele, dan kunnen we een situatie hebben waarin we zouden kunnen proberen de grayWolf- variabele te gebruiken om een ​​methode aan te roepen die niet bestaat in het Cat-object dat in die variabele is opgeslagen . Daarom is deze regeling niet toegestaan.

Java heeft een speciale instanceofoperator waarmee u kunt controleren of een object van een bepaald type is en daarom kan worden opgeslagen in een variabele van een bepaald type. Het ziet er vrij simpel uit:

variable instanceof Type

Voorbeeld:

Animal beast = new Cat();
if (beast instanceof Wolf)
{
   Wolf grayWolf = (Wolf) beast;
}

Deze code veroorzaakt geen fouten, zelfs niet tijdens runtime.

Hier zijn nog enkele voorbeelden die de situatie illustreren:

Verbreding type conversie Beschrijving
Cow cow = new Whale();

Dit is een klassieke verbredingsconversie — er is geen operator voor typeconversie vereist. Nu kunnen alleen de methoden die in de klasse zijn gedefinieerd, op het object Cowworden aangeroepen .Whale

Op de cowvariabele laat de compiler je alleen methoden aanroepen die zijn type (de Cowklasse) heeft.

Vernauwende typeconversie
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Klassieke vernauwingsconversie: u moet een typecontrole en een cast-operator toevoegen.
De Cow cowvariabele slaat een verwijzing naar een Whaleobject op.
We verifiëren dat dit het geval is en voeren vervolgens een (vernauwende) typeconversie uit. Of zoals het ook wel heet:
een typecast
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
U kunt een referentietype verfijnen zonder het type van het object te controleren.
Als de cowvariabele verwijst naar een object dat geen is Whale, InvalidClassCastExceptionwordt er een gegenereerd.


3. De oorspronkelijke methode aanroepen: het supertrefwoord

Wanneer we de methode van een bovenliggende klasse overschrijven, willen we deze soms niet vervangen door onze eigen methode, maar een beetje aanvullen.

Het zou cool zijn als we de methode van de ouderklasse in onze methode zouden kunnen gebruiken en dan wat van onze eigen code zouden kunnen uitvoeren. Of voer misschien eerst onze eigen code uit en roep vervolgens de methode van de bovenliggende klasse aan.

En Java stelt ons in staat om precies dat te doen. Ga als volgt te werk om een ​​methode van de bovenliggende klasse aan te roepen:

super.method(arguments);

Voorbeelden:

class PeaceTime
{
   public double getPi()
   {
      return 3.14;
   }
}

class WarTime extends PeaceTime
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

In oorlogstijd Pikan de waarde van groter zijn dan 6! We maken natuurlijk een grapje, maar dit voorbeeld laat zien hoe dit allemaal kan werken.

Hier zijn nog een paar voorbeelden om de zaken een beetje te verduidelijken:

Code Beschrijving
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.print("This is incorrect: ");
      super.printName();
      System.out.println("I'm a whale");
   }
}
Cowen Whaleklassen
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
De schermuitvoer is:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

Dit is moeilijk spul. Eerlijk gezegd, het is een van de moeilijkste dingen in OOP . Dat gezegd hebbende, je moet het wel kennen en begrijpen.