JavaRush /Java-Blog /Random-DE /Erweiterung und Kontraktion von Referenztypen

Erweiterung und Kontraktion von Referenztypen

Veröffentlicht in der Gruppe Random-DE
Hallo! In einer der vorherigen Vorlesungen haben wir die Umwandlung primitiver Typen besprochen. Erinnern wir uns kurz daran, worüber wir gesprochen haben. Erweiterung und Kontraktion von Referenztypen - 1Wir haben primitive Typen (in diesem Fall numerisch) als Nistpuppen dargestellt, entsprechend der Menge an Speicher, die sie belegen. Wie Sie sich erinnern, wird es sowohl im echten Leben als auch in der Java-Programmierung einfach sein, eine kleinere Nistpuppe in eine größere zu stecken.

public class Main {
   public static void main(String[] args) {
        short smallNumber = 100;
        int bigNumber =  smallNumber;
        System.out.println(bigNumber);
   }
}
Dies ist ein Beispiel für eine automatische Konvertierung oder Erweiterung . Dies geschieht von selbst, sodass kein zusätzlicher Code geschrieben werden muss. Am Ende machen wir nichts Ungewöhnliches: Wir stecken einfach eine kleinere Matroschka-Puppe in eine größere Matroschka-Puppe. Eine andere Sache ist es, wenn wir das Gegenteil versuchen und eine große Matroschka-Puppe in eine kleinere stecken. Dies ist im Leben nicht möglich, aber in der Programmierung ist es möglich. Aber es gibt eine Einschränkung. intWenn wir versuchen, einen Wert in eine Variable einzugeben short, wird das nicht so einfach klappen. Schließlich passen nur 16 Bit an Informationen in eine Variable short, aber der Wert intbenötigt 32 Bit! Dadurch wird der übertragene Wert verfälscht. Der Compiler gibt uns eine Fehlermeldung („ Alter, du machst etwas Verdächtiges! “), aber wenn wir explizit angeben, in welchen Typ wir unseren Wert umwandeln, führt er trotzdem einen solchen Vorgang aus.

public class Main {

   public static void main(String[] args) {

       int bigNumber = 10000000;

       bigNumber = (short) bigNumber;

       System.out.println(bigNumber);

   }

}
Im obigen Beispiel haben wir genau das getan. Die Operation wurde abgeschlossen, aber da shortnur 16 der 32 Bits in die Variable passten, war der Endwert verzerrt und als Ergebnis erhielten wir die Zahl -27008 . Dieser Vorgang wird als explizite Konvertierung oder Eingrenzung bezeichnet .

Beispiele für Erweiterung und Kontraktion von Referenztypen

Jetzt werden wir über dieselben Operationen sprechen, die jedoch nicht auf primitive Typen anwendbar sind, sondern auf Objekte und Referenzvariablen ! Wie funktioniert das in Java? Eigentlich ganz einfach. Es gibt Objekte, die nicht miteinander in Zusammenhang stehen. Es wäre logisch anzunehmen, dass sie weder explizit noch automatisch ineinander konvertiert werden können:

public class Cat {
}

public class Dog {
}

public class Main {

   public static void main(String[] args) {

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

   }

}
Hier erhalten wir natürlich einen Fehler. Die Klassen Catsind Dognicht miteinander verbunden und wir haben keinen „Konverter“ von einer zur anderen geschrieben. Dass uns das nicht gelingt, ist logisch: Der Compiler hat keine Ahnung, wie er diese Objekte untereinander konvertieren soll. Eine andere Sache ist es, wenn die Objekte miteinander verbunden sind! Wie? Zunächst einmal die Vererbung. Versuchen wir, ein kleines Klassensystem mit Vererbung zu erstellen. Wir werden eine allgemeine Klasse haben, die Tiere darstellt:

public class Animal {
  
   public void introduce() {

       System.out.println("i'm Animal");
   }
}
Tiere sind, wie Sie wissen, heimisch und wild:

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");
   }
}
Nehmen wir zum Beispiel Hunde – einen Haushund und einen Kojoten:

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");
   }
}
Unsere Klassen sind bewusst am primitivsten gehalten, um sie leichter verständlich zu machen. Wir brauchen hier nicht wirklich Felder und eine Methode reicht aus. Versuchen wir, den folgenden Code auszuführen:

public class Main {

   public static void main(String[] args) {

       Animal animal = new Pet();
       animal.introduce();
   }
}
Was wird Ihrer Meinung nach auf der Konsole ausgegeben? Funktioniert die introduceKlasse Petoder Klassenmethode Animal? Versuchen Sie, Ihre Antwort zu begründen, bevor Sie weiterlesen. Und hier ist das Ergebnis! Ich bin Pet. Warum ist die Antwort so ausgefallen? Es ist einfach. Wir haben eine übergeordnete Variable und ein untergeordnetes Objekt. Durch Schreiben:

Animal animal = new Pet();
Wir haben einen Referenztyp erweitertPet und sein Objekt in einer Variablen gespeichert Animal. Wie bei primitiven Typen erfolgt die Erweiterung von Referenztypen in Java automatisch. Hierfür muss kein zusätzlicher Code geschrieben werden. Jetzt haben wir ein untergeordnetes Objekt an die übergeordnete Referenz angehängt und sehen als Ergebnis, dass die Methode für die untergeordnete Klasse aufgerufen wird. Wenn Sie immer noch nicht vollständig verstehen, warum dieser Code funktioniert, schreiben Sie ihn in einfacher Sprache um:

Животное животное = new ДомашнееЖивотное();
Das ist doch kein Problem, oder? Stellen Sie sich vor, das wäre das wirkliche Leben, und der Link ist in diesem Fall ein einfacher Papieranhänger mit der Aufschrift „Tier“. Wenn Sie ein solches Stück Papier nehmen und es am Halsband eines beliebigen Haustiers befestigen, ist alles gut. Jedes Haustier ist immer noch ein Tier! Der umgekehrte Vorgang, also das Verschieben im Erbschaftsbaum nach unten zu den Erben, ist eine Einengung:

public class Main {

   public static void main(String[] args) {

       WildAnimal wildAnimal = new Coyote();

       Coyote coyote = (Coyote) wildAnimal;

       coyote.introduce();
   }
}
Wie Sie sehen, geben wir hier explizit an, in welche Klasse wir unser Objekt umwandeln möchten. Zuvor hatten wir eine Variable WildAnimal, und jetzt Coyote, die im Vererbungsbaum nach unten geht. Es ist logisch, dass der Compiler einen solchen Vorgang nicht ohne explizite Angabe überspringt, aber wenn Sie den Typ in Klammern angeben, wird alles funktionieren. Erweiterung und Kontraktion von Referenztypen - 2 Schauen wir uns ein anderes, interessanteres Beispiel an:

public class Main {

   public static void main(String[] args) {

       Pet pet = new Animal();//Fehler!
   }
}
Der Compiler gibt einen Fehler aus! Was ist der Grund? Tatsache ist, dass Sie versuchen, einer untergeordneten Variablen ein übergeordnetes Objekt zuzuweisen. Mit anderen Worten, Sie möchten Folgendes tun:

ДомашнееЖивотное домашнееЖивотное = new Животное();
Aber vielleicht gelingt es uns, wenn wir den Typ, in den wir umwandeln möchten, explizit angeben? Die Zahlen scheinen zu funktionieren, versuchen wir es! :) :)

public class Main {

   public static void main(String[] args) {
      
       Pet pet = (Pet) new Animal();
   }
}
Ausnahme im Thread „main“ java.lang.ClassCastException: Tier kann nicht in Haustierfehler umgewandelt werden ! Der Compiler hat sich dieses Mal nicht beschwert, aber als Ergebnis haben wir eine Ausnahme erhalten. Den Grund kennen wir bereits: Wir versuchen, einer untergeordneten Variablen ein übergeordnetes Objekt zuzuweisen. Warum ist das eigentlich nicht möglich? Denn nicht alle Tiere sind Haustiere. Sie haben ein Objekt erstellt Animalund versuchen, es einer Variablen zuzuweisen Pet. Aber zum Beispiel ist ein Kojote auch ein Haustier Animal, aber es ist kein PetHaustier. Mit anderen Worten, wenn Sie schreiben:

Pet pet = (Pet) new Animal();
new Animal()Jedes Tier kann dabei sein, es muss kein Haustier sein! Natürlich Pet petist Ihre Variable nur zum Speichern von Haustieren (und deren Nachkommen) geeignet und nicht für jedermann. Daher wurde für solche Fälle in Java eine spezielle Ausnahme erstellt – ClassCastExceptionein Fehler beim Casting von Klassen. Sagen wir es noch einmal, um es klarer zu machen. Eine übergeordnete Variable (Referenz) kann auf ein Objekt einer untergeordneten Klasse verweisen:

public class Main {

   public static void main(String[] args) {

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

       Pet pet2 = (Pet) animal;
       pet2.introduce();
   }
}
Hier werden wir zum Beispiel keine Probleme haben. Wir haben ein Objekt Pet, auf das durch einen Link verwiesen wird Pet. Dann begann ein neuer Link auf dasselbe Objekt zu verweisen Animal. Anschließend führen wir die Konvertierung animaldurch Pet. Warum haben wir das übrigens getan? Beim letzten Mal gab es eine Ausnahme! Denn dieses Mal ist unser ursprüngliches Objekt Pet pet!

Pet pet =  new Pet();
Und im vorherigen Beispiel war es ein Objekt Animal:

Pet pet = (Pet) new Animal();
Einer Nachkommenvariablen kann kein Vorgängerobjekt zugewiesen werden. Im Gegenteil, Sie können es schaffen.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION