Java Type Systemインタビューの質問
1. 前書き
Java Type Systemは、Java開発者向けの技術面接でよく取り上げられるトピックです。 この記事では、最も頻繁に尋ねられる重要な質問を確認します。
2. 質問
Q1. 型階層内のオブジェクトクラスの場所を説明します。 オブジェクトから継承するタイプと、しないタイプ 配列はオブジェクトから継承されますか? ラムダ式をオブジェクト変数に割り当てることはできますか?
java.lang.Objectは、Javaのクラス階層の最上位にあります。 すべてのクラスは、明示的、暗黙的(extendsキーワードがクラス定義から省略されている場合)、または継承のチェーンを介して推移的に継承します。
ただし、Objectから継承しない8つのプリミティブ型、つまりboolean、byte、short、char、int、%があります。 (t6)s、long、およびdouble。
Java言語仕様によれば、配列もオブジェクトです。 それらはObject参照に割り当てることができ、すべてのObjectメソッドを呼び出すことができます。
Objectは関数型インターフェースではないため、ラムダ式をObject変数に直接割り当てることはできません。 ただし、ラムダを関数型インターフェイス変数に割り当ててから、Object変数に割り当てることができます(または、関数型インターフェイスに同時にキャストして、オブジェクト変数に割り当てることもできます)。
Q2. プリミティブ型と参照型の違いを説明します。
参照型は最上位のjava.lang.Objectクラスから継承し、それ自体が継承可能です(finalクラスを除く)。 プリミティブ型は継承せず、サブクラス化できません。
プリミティブ型の引数値は常にスタックを介して渡されます。つまり、参照ではなく値で渡されます。 これには、次のような意味があります。メソッド内のプリミティブ引数値に加えられた変更は、実際の引数値に反映されません。
プリミティブ型は通常、基礎となるハードウェア値型を使用して保存されます。
たとえば、int値を格納するには、32ビットのメモリセルを使用できます。 参照型は、参照型のすべてのインスタンスに存在するオブジェクトヘッダーのオーバーヘッドをもたらします。
オブジェクトヘッダーのサイズは、単純な数値のサイズに関連して非常に重要になる場合があります。 これが、オブジェクトのオーバーヘッドのスペースを節約するために、最初にプリミティブ型が導入された理由です。 欠点は、Javaのすべてが技術的にオブジェクトであるとは限らないことです。プリミティブ値は、Objectクラスから継承されません。
Q3. さまざまなプリミティブ型とそれらが占めるメモリの量を説明します。
Javaには8つのプリミティブ型があります。
-
boolean —論理true /false値。 ブール値のサイズはJVM仕様で定義されておらず、実装によって異なる場合があります。
-
byte —符号付き8ビット値、
-
short —符号付き16ビット値、
-
char —符号なし16ビット値。
-
int —符号付き32ビット値。
-
long —符号付き64ビット値。
-
float — IEEE754標準に対応する32ビットの単精度浮動小数点値。
-
double — IEEE754標準に対応する64ビットの倍精度浮動小数点値。
Q4. 抽象クラスとインターフェイスの違いは何ですか? 一方と他方のユースケースは何ですか?
抽象クラスは、定義にabstract修飾子が含まれるclassです。 インスタンス化することはできませんが、サブクラス化することはできます。 インターフェイスは、interfaceキーワードで記述されたタイプです。 インスタンス化することもできませんが、実装することはできます。
抽象クラスとインターフェイスの主な違いは、クラスが複数のインターフェイスを実装できるが、1つの抽象クラスのみを拡張できることです。
abstractクラスは通常、一部のクラス階層で基本型として使用され、それを継承するすべてのクラスの主な目的を示します。
abstractクラスは、すべてのサブクラスで必要ないくつかの基本的なメソッドを実装することもできます。 たとえば、JDKのほとんどのマップコレクションは、サブクラスで使用される多くのメソッド(equalsメソッドなど)を実装するAbstractMapクラスを継承します。
インターフェイスは、クラスが同意する契約を指定します。 実装されたインターフェースは、クラスの主な意図だけでなく、いくつかの追加の契約も意味する場合があります。
たとえば、クラスがComparableインターフェイスを実装している場合、これは、このクラスの主な目的が何であれ、このクラスのインスタンスを比較できることを意味します。
Q5. インターフェイスタイプのメンバー(フィールドとメソッド)の制限は何ですか?
インターフェイスはフィールドを宣言できますが、これらの修飾子を指定しなくても、フィールドはpublic、static、およびfinalとして暗黙的に宣言されます。 したがって、インターフェースフィールドをprivateとして明示的に定義することはできません。 本質的に、インターフェイスにはインスタンスフィールドではなく、定数フィールドのみを含めることができます。
インターフェイスのすべてのメソッドも暗黙的にpublicです。 また、(暗黙的に)abstractまたはdefaultのいずれかになります。
Q6. 内部クラスと静的ネストクラスの違いは何ですか?
入れ子にしたクラスは、基本的に別のクラス内で定義されたクラスです。
ネストされたクラスは、プロパティが大きく異なる2つのカテゴリに分類されます。 内部クラスは、囲んでいるクラスを最初にインスタンス化しないとインスタンス化できないクラスです。 内部クラスのインスタンスは、それを囲むクラスのインスタンスに暗黙的にバインドされます。
内部クラスの例を次に示します。OuterClass1.this構造の形式で外部クラスインスタンスへの参照にアクセスできることがわかります。
public class OuterClass1 {
public class InnerClass {
public OuterClass1 getOuterInstance() {
return OuterClass1.this;
}
}
}
このような内部クラスをインスタンス化するには、外部クラスのインスタンスが必要です。
OuterClass1 outerClass1 = new OuterClass1();
OuterClass1.InnerClass innerClass = outerClass1.new InnerClass();
静的にネストされたクラスはまったく異なります。 構文的には、定義にstatic修飾子が含まれるネストされたクラスです。
実際には、このクラスは、それを囲むクラスのインスタンスにバインドせずに、他のクラスとしてインスタンス化できることを意味します。
public class OuterClass2 { public static class StaticNestedClass { } }
このようなクラスをインスタンス化するために、外部クラスのインスタンスは必要ありません。
OuterClass2.StaticNestedClass staticNestedClass = new OuterClass2.StaticNestedClass();
Q7. Javaには多重継承がありますか?
Javaはクラスの多重継承をサポートしていません。つまり、クラスは単一のスーパークラスからのみ継承できます。
ただし、1つのクラスで複数のインターフェイスを実装できます。これらのインターフェイスのメソッドの一部はdefaultとして定義され、実装されている場合があります。 これにより、異なる機能を単一のクラスに混在させるより安全な方法を使用できます。
Q8. ラッパークラスとは オートボクシングとは何ですか?
Javaの8つのプリミティブ型のそれぞれには、プリミティブ値をラップしてオブジェクトのように使用するために使用できるラッパークラスがあります。 これらのクラスは、対応して、Boolean、Byte、Short、Character、Integer、Float、Long、および%です。 (t7)s。 これらのラッパーは、たとえば、参照オブジェクトのみを受け入れる汎用コレクションにプリミティブ値を配置する必要がある場合に役立ちます。
List list = new ArrayList<>();
list.add(new Integer(5));
プリミティブを手動で前後に変換する手間を省くために、Javaコンパイラーによりオートボックス化/自動ボックス化解除と呼ばれる自動変換が提供されます。
List list = new ArrayList<>();
list.add(5);
int value = list.get(0);
Q9. Equals()と==の違いを説明する
==演算子を使用すると、2つのオブジェクトの「同一性」を比較できます(つまり、 両方の変数がメモリ内の同じオブジェクトを参照していること)。 newキーワードは常に、他のオブジェクトと同じ値を持っているように見えても、==の同等性を渡さない新しいオブジェクトを作成することを覚えておくことが重要です。
String string1 = new String("Hello");
String string2 = new String("Hello");
assertFalse(string1 == string2);
また、==演算子を使用すると、プリミティブ値を比較できます。
int i1 = 5;
int i2 = 5;
assertTrue(i1 == i2);
equals()メソッドはjava.lang.Objectクラスで定義されているため、どの参照型でも使用できます。 デフォルトでは、==演算子を使用してオブジェクトが同じであることを確認するだけです。 ただし、サブクラスでは通常、クラスの比較の特定のセマンティクスを提供するためにオーバーライドされます。
たとえば、Stringクラスの場合、このメソッドは文字列に同じ文字が含まれているかどうかを確認します。
String string1 = new String("Hello");
String string2 = new String("Hello");
assertTrue(string1.equals(string2));
Q10. クラス型のインスタンスを参照する変数があるとします。 オブジェクトがこのクラスのインスタンスであることをどのように確認しますか?
この場合、instanceofキーワードは、実際のクラス名をリテラルとして指定した場合にのみ機能するため、使用できません。
ありがたいことに、Classクラスには、オブジェクトがこのクラスのインスタンスであるかどうかを確認できるメソッドisInstanceがあります。
Class> integerClass = new Integer(5).getClass();
assertTrue(integerClass.isInstance(new Integer(4)));
Q11. 匿名クラスとは何ですか? そのユースケースを説明してください。
匿名クラスは、そのインスタンスが必要な同じ場所で定義されるワンショットクラスです。 このクラスは同じ場所で定義およびインスタンス化されるため、名前は必要ありません。
Java 8より前は、匿名クラスを使用して、Runnableなどの単一のメソッドインターフェイスの実装を定義することがよくありました。 Java 8では、単一の抽象メソッドインターフェイスの代わりにラムダが使用されます。 ただし、たとえば、複数のメソッドを持つインターフェイスのインスタンスや、機能が追加されたクラスのインスタンスが必要な場合など、匿名クラスにはまだユースケースがあります。
マップを作成してデータを入力する方法は次のとおりです。
Map ages = new HashMap(){{
put("David", 30);
put("John", 25);
put("Mary", 29);
put("Sophie", 22);
}};