Java Type System - Interviewfragen

Fragen in Vorstellungsgesprächen bei Java Type System

1. Einführung

Java Type System ist ein Thema, das häufig in technischen Interviews für Java-Entwickler zur Sprache kommt. In diesem Artikel werden einige wichtige Fragen besprochen, die am häufigsten gestellt werden und möglicherweise schwierig zu beantworten sind.

2. Fragen

Q1. Beschreiben Sie die Position der Objektklasse in der Typhierarchie. Welche Typen erben von Object und welche nicht? Vererben Arrays von Object? Kann ein Lambda-Ausdruck einer Objektvariablen zugewiesen werden?

Dasjava.lang.Object steht in Java an der Spitze der Klassenhierarchie. Alle Klassen erben davon entweder explizit, implizit (wenn das Schlüsselwortextendsin der Klassendefinition weggelassen wird) oder transitiv über die Vererbungskette.

Es gibt jedoch acht primitive Typen, die nicht vonObject erben, nämlichboolean,byte,short,char,int,float,long unddouble.

Nach der Java-Sprachspezifikation sind Arrays auch Objekte. Sie können einerObject-Referenz zugewiesen werden, und alleObject-Methoden können für sie aufgerufen werden.

Lambda-Ausdrücke können nicht direkt einerObject-Variablen zugewiesen werden, daObject keine funktionale Schnittstelle ist. Sie können jedoch einer funktionalen Schnittstellenvariablen ein Lambda zuweisen und es dann einerObject-Variablen zuweisen (oder es einfach einer Objektvariablen zuweisen, indem Sie es gleichzeitig einer funktionalen Schnittstelle umwandeln).

 

Q2. Erklären Sie den Unterschied zwischen primitiven und Referenztypen.

Referenztypen erben von der oberstenjava.lang.Object-Klasse und sind selbst vererbbar (mit Ausnahme derfinal-Klassen). Primitive Typen erben nicht und können nicht in Unterklassen unterteilt werden.

Primitiv typisierte Argumentwerte werden immer über den Stack übergeben, dh sie werden nach Wert und nicht nach Referenz übergeben. Dies hat folgende Auswirkungen: Änderungen an einem primitiven Argumentwert innerhalb der Methode werden nicht an den tatsächlichen Argumentwert weitergegeben.

Primitive Typen werden normalerweise unter Verwendung der zugrunde liegenden Hardware-Werttypen gespeichert.

Zum Speichern einesint-Werts kann beispielsweise eine 32-Bit-Speicherzelle verwendet werden. Referenztypen führen den Overhead des Objektheaders ein, der in jeder Instanz eines Referenztyps vorhanden ist.

Die Größe eines Objektkopfes kann im Verhältnis zu einer einfachen numerischen Wertgröße sehr bedeutend sein. Aus diesem Grund wurden die primitiven Typen eingeführt, um Platz auf dem Objekt-Overhead zu sparen. Der Nachteil ist, dass technisch gesehen nicht alles in Java ein Objekt ist - primitive Werte erben nicht von der KlasseObject.

 

Q3. Beschreiben Sie die verschiedenen primitiven Typen und die Menge an Speicher, die sie belegen.

Java hat 8 primitive Typen:

  • boolean - logischer Wert vontrue /false. Die Größe des Booleschen Werts ist nicht in der JVM-Spezifikation definiert und kann in verschiedenen Implementierungen variieren.

  • byte - vorzeichenbehafteter 8-Bit-Wert,

  • short - vorzeichenbehafteter 16-Bit-Wert,

  • char - vorzeichenloser 16-Bit-Wert,

  • int - vorzeichenbehafteter 32-Bit-Wert,

  • long - vorzeichenbehafteter 64-Bit-Wert,

  • float - 32-Bit-Gleitkommawert mit einfacher Genauigkeit entsprechend dem IEEE 754-Standard,

  • double - 64-Bit-Gleitkommawert mit doppelter Genauigkeit, entsprechend dem IEEE 754-Standard.

 

Q4. Was ist der Unterschied zwischen einer abstrakten Klasse und einer Schnittstelle? Was sind die Anwendungsfälle des einen und des anderen?

Eine abstrakte Klasse ist einclass mit dem Modifikatorabstract in seiner Definition. Es kann nicht instanziiert, aber in Unterklassen unterteilt werden. Die Schnittstelle ist ein Typ, der mit dem Schlüsselwortinterfacebeschrieben wird. Es kann auch nicht instanziiert werden, aber es kann implementiert werden.

Der Hauptunterschied zwischen einer abstrakten Klasse und einer Schnittstelle besteht darin, dass eine Klasse mehrere Schnittstellen implementieren kann, jedoch nur eine abstrakte Klasse erweitert.

Die Klasseabstractwird normalerweise in einigen Klassenhierarchien als Basistyp verwendet und zeigt die Hauptabsicht aller Klassen an, die von ihr erben.

Eineabstract-Klasse könnte auch einige grundlegende Methoden implementieren, die in allen Unterklassen benötigt werden. Beispielsweise erben die meisten Kartensammlungen in JDK von der KlasseAbstractMap, die viele von Unterklassen verwendete Methoden implementiert (z. B. die Methodeequals).

Eine Schnittstelle gibt einen Vertrag an, dem die Klasse zustimmt. Eine implementierte Schnittstelle kann nicht nur die Hauptabsicht der Klasse angeben, sondern auch einige zusätzliche Verträge.

Wenn eine Klasse beispielsweise dieComparable-Schnittstelle implementiert, bedeutet dies, dass Instanzen dieser Klasse verglichen werden können, unabhängig vom Hauptzweck dieser Klasse.

 

Q5. Was sind die Einschränkungen für die Elemente (Felder und Methoden) eines Schnittstellentyps?

Eine Schnittstelle kann Felder deklarieren, diese werden jedoch implizit alspublic,static undfinal deklariert, auch wenn Sie diese Modifikatoren nicht angeben. Folglich können Sie ein Schnittstellenfeld nicht explizit alsprivate definieren. Im Wesentlichen darf eine Schnittstelle nur konstante Felder haben, keine Instanzfelder.

Alle Methoden einer Schnittstelle sind implizit auchpublic. Sie können auch entweder (implizit)abstract oderdefault sein.

 

Q6. Was ist der Unterschied zwischen einer inneren Klasse und einer statisch verschachtelten Klasse?

Einfach ausgedrückt: Eine verschachtelte Klasse ist im Grunde eine Klasse, die in einer anderen Klasse definiert ist.

Geschachtelte Klassen lassen sich in zwei Kategorien mit sehr unterschiedlichen Eigenschaften einteilen. Eine innere Klasse ist eine Klasse, die nicht instanziiert werden kann, ohne zuerst die einschließende Klasse zu instanziieren, d. H. Jede Instanz einer inneren Klasse ist implizit an eine Instanz der einschließenden Klasse gebunden.

Hier ist ein Beispiel für eine innere Klasse: Sie können sehen, dass sie in Form des KonstruktsOuterClass1.thisauf den Verweis auf die Instanz der äußeren Klasse zugreifen kann:

public class OuterClass1 {

    public class InnerClass {

        public OuterClass1 getOuterInstance() {
            return OuterClass1.this;
        }

    }

}

Um eine solche innere Klasse zu instanziieren, benötigen Sie eine Instanz einer äußeren Klasse:

OuterClass1 outerClass1 = new OuterClass1();
OuterClass1.InnerClass innerClass = outerClass1.new InnerClass();

Statisch verschachtelte Klassen sind ganz anders. Syntaktisch handelt es sich nur um eine verschachtelte Klasse mit dem Modifikatorstaticin der Definition.

In der Praxis bedeutet dies, dass diese Klasse wie jede andere Klasse instanziiert werden kann, ohne sie an eine Instanz der einschließenden Klasse zu binden:

public class OuterClass2 {

    public static class StaticNestedClass {
    }

}

Um eine solche Klasse zu instanziieren, benötigen Sie keine Instanz der äußeren Klasse:

OuterClass2.StaticNestedClass staticNestedClass = new OuterClass2.StaticNestedClass();

 

Q7. Hat Java eine Mehrfachvererbung?

Java unterstützt die Mehrfachvererbung für Klassen nicht. Dies bedeutet, dass eine Klasse nur von einer einzelnen Superklasse erben kann.

Sie können jedoch mehrere Schnittstellen mit einer einzigen Klasse implementieren, und einige der Methoden dieser Schnittstellen können alsdefault definiert sein und eine Implementierung haben. Auf diese Weise können Sie sicherer verschiedene Funktionen in einer Klasse mischen.

 

Q8. Was sind die Wrapper-Klassen? Was ist Autoboxing?

Für jeden der acht Grundtypen in Java gibt es eine Wrapper-Klasse, mit der ein Grundwert umbrochen und wie ein Objekt verwendet werden kann. Diese Klassen sind entsprechendBoolean,Byte,Short,Character,Integer,Float,Long undDouble. Diese Wrapper können beispielsweise nützlich sein, wenn Sie einen primitiven Wert in eine generische Auflistung einfügen müssen, die nur Referenzobjekte akzeptiert.

List list = new ArrayList<>();
list.add(new Integer(5));

Um das manuelle Konvertieren von Grundelementen hin und her zu vermeiden, stellt der Java-Compiler eine automatische Konvertierung bereit, die als Autoboxing / Auto Unboxing bezeichnet wird.

List list = new ArrayList<>();
list.add(5);
int value = list.get(0);

 

Q9. Beschreiben Sie den Unterschied zwischen Equals () und ==

Mit dem Operator == können Sie zwei Objekte auf "Gleichheit" vergleichen (d. H. dass beide Variablen auf dasselbe Objekt im Speicher verweisen). Es ist wichtig zu beachten, dass das Schlüsselwortnewimmer ein neues Objekt erstellt, das die Gleichheit von==mit keinem anderen Objekt besteht, selbst wenn sie denselben Wert zu haben scheinen:

String string1 = new String("Hello");
String string2 = new String("Hello");

assertFalse(string1 == string2);

Der Operator == ermöglicht auch den Vergleich von Grundwerten:

int i1 = 5;
int i2 = 5;

assertTrue(i1 == i2);

Die Methodeequals() ist in der Klassejava.lang.Objectdefiniert und steht daher für jeden Referenztyp zur Verfügung. Standardmäßig wird lediglich über den Operator == überprüft, ob das Objekt identisch ist. In Unterklassen wird es jedoch normalerweise überschrieben, um die spezifische Vergleichssemantik für eine Klasse bereitzustellen.

Für die KlasseStringprüft diese Methode beispielsweise, ob die Zeichenfolgen dieselben Zeichen enthalten:

String string1 = new String("Hello");
String string2 = new String("Hello");

assertTrue(string1.equals(string2));

 

Q10. Angenommen, Sie haben eine Variable, die auf eine Instanz eines Klassentyps verweist. Wie überprüfen Sie, ob ein Objekt eine Instanz dieser Klasse ist?

In diesem Fall können Sie das Schlüsselwortinstanceofnicht verwenden, da es nur funktioniert, wenn Sie den tatsächlichen Klassennamen als Literal angeben.

Zum Glück verfügt die KlasseClassüber eine MethodeisInstance, mit der überprüft werden kann, ob ein Objekt eine Instanz dieser Klasse ist:

Class integerClass = new Integer(5).getClass();
assertTrue(integerClass.isInstance(new Integer(4)));

 

Q11. Was ist eine anonyme Klasse? Beschreiben Sie den Anwendungsfall.

Die anonyme Klasse ist eine One-Shot-Klasse, die an derselben Stelle definiert wird, an der ihre Instanz benötigt wird. Diese Klasse wird an derselben Stelle definiert und instanziiert und benötigt daher keinen Namen.

Vor Java 8 verwendeten Sie häufig eine anonyme Klasse, um die Implementierung einer einzelnen Methodenschnittstelle wieRunnable zu definieren. In Java 8 werden Lambdas anstelle einzelner abstrakter Methodenschnittstellen verwendet. Anonyme Klassen haben jedoch immer noch Anwendungsfälle, z. B. wenn Sie eine Instanz einer Schnittstelle mit mehreren Methoden oder eine Instanz einer Klasse mit einigen hinzugefügten Funktionen benötigen.

So können Sie eine Karte erstellen und füllen:

Map ages = new HashMap(){{
    put("David", 30);
    put("John", 25);
    put("Mary", 29);
    put("Sophie", 22);
}};