Javaインタビューの質問

Javaインタビューの質問

1. 前書き

この記事には、コアJavaに関する最も重要な就職面接の質問に対する回答が含まれています。 それらのいくつかに対する答えは明らかではないかもしれないので、この記事は物事を明確にするのに役立ちます。

2. 初心者向けのコアJava言語の質問

Q1. データはJavaの参照または値によって渡されますか?

この質問に対する答えは非常に単純ですが、初心者にとってはこの質問は混乱を招く可能性があります。 まず、質問の内容を明確にしましょう。

  1. Passing by value –は、a copy of an objectをパラメータとしてメソッドに渡すことを意味します。

  2. Passing by reference –は、a reference to an objectをパラメータとしてメソッドに渡すことを意味します。

質問に答えるには、2つのケースを分析する必要があります。 これらは、メソッドに渡すことができる2つのタイプのデータを表します。プリミティブとオブジェクトです。

メソッドにプリミティブを渡すと、その値が新しい変数にコピーされます。 オブジェクトに関しては、参照の値が新しい変数にコピーされます。 So we can say that Java is a strictly pass-by-value language.

詳細については、記事の1つであるPass-By-Value as a Parameter Passing Mechanism in Javaをご覧ください。

Q2. インポートと静的インポートの違いは何ですか?

通常のインポートを使用して、特定のクラスまたは別のパッケージで定義されたすべてのクラスをインポートできます。

import java.util.ArrayList; //specific class
import java.util.*; //all classes in util package

それらを使用して、包含クラスのネストされたパブリッククラスをインポートすることもできます。

import com.example.A.*

ただし、上記のインポートでは、クラスA自体はインポートされないことに注意してください。

静的メンバーまたはネストされたクラスをインポートできる静的インポートもあります。

import static java.util.Collections.EMPTY_LIST;

その効果は、完全修飾クラス名を追加せずに静的変数EMPTY_LISTを使用できることです。 現在のクラスで宣言されているかのように。

Q3. Javaで利用可能なアクセス修飾子とその目的は何ですか?

Javaには4つのアクセス修飾子があります。

  1. 非公開

  2. default(パッケージ)

  3. 保護された

  4. パブリック

The private modifier assures that class members won’t be accessible outside the class.メソッド、プロパティ、コンストラクター、ネストされたクラスに適用できますが、トップレベルクラス自体には適用できません。

private修飾子とは異なり、default修飾子をすべてのタイプのクラスメンバーとクラス自体に適用できます。 アクセス修飾子をまったく追加しないことで、defaultの可視性を適用できます。 If we use default visibility our class or its members will be accessible only inside the package of our class. デフォルトのアクセス修飾子にはdefaultキーワードとの共通点がないことに注意してください。

default修飾子と同様に、1つのパッケージ内のすべてのクラスがprotectedメンバーにアクセスできます。 What’s more, the protected modifier allows subclasses to access the protected members of a superclass, even if they are not within the same package.このアクセス修飾子をクラスに適用することはできません。クラスメンバーにのみ適用できます。

public修飾子は、classキーワードおよびすべてのクラスメンバーと一緒に使用できます。 It makes classes and class members accessible in all packages and by all classes.

詳細については、Java Access Modifiersの記事をご覧ください。

Q4. Javaで使用できる他の修飾子とその目的は何ですか?

Javaには、他にも5つの修飾子があります。

  • 静的

  • 最後の

  • 抽象

  • 同期された

  • 揮発性

これらは可視性を制御しません。

まず、staticキーワードをフィールドとメソッドに適用できます。 Static fields or methods are class members, whereas non-static ones are object members。 クラスメンバーは、インスタンスを呼び出す必要はありません。 オブジェクト参照名の代わりにクラス名で呼び出されます。 This articleでは、staticキーワードについて詳しく説明します。

次に、finalキーワードがあります。 フィールド、メソッド、クラスで使用できます。 When final is used on a field, it means that the field reference cannot be changed.したがって、別のオブジェクトに再割り当てすることはできません。 When final is applied to a class or a method, it assures us that that class or method cannot be extended or overridden.finalキーワードについては、this articleで詳しく説明しています。

次のキーワードはabstractです。 これはクラスとメソッドを記述することができます。 When classes are abstract, they can’t be instantiated.代わりに、サブクラス化することを目的としています。 メソッドがabstractの場合、実装せずに残し、サブクラスでオーバーライドできます。

synchronizedキーワードが最も高度な場合があります。 インスタンスだけでなく、静的メソッドやコードブロックでも使用できます。 When we use this keyword, we make Java use a monitor lock to provide synchronization on a given code fragment.synchronizedの詳細については、this articleを参照してください。

ここで説明する最後のキーワードはvolatileです。 インスタンスフィールドと一緒にしか使用できません。 It declares that the field value must be read from and written to main memory – bypassing the CPU cache.揮発性変数のすべての読み取りと書き込みはアトミックです。 volatileキーワードについては、this articleで詳しく説明されています。

Q5. JDK、JRE、およびJVMの違いは何ですか?

JDKJava Development Kitの略で、開発者がJavaでアプリケーションを作成するために必要なツールのセットです。 JDK環境には3つのタイプがあります。

  • Standard Edition –ポータブルデスクトップまたはサーバーアプリケーションを作成するための開発キット

  • Enterprise Edition –分散コンピューティングまたはWebサービスをサポートするStandard Editionの拡張機能

  • Micro Edition –組み込みおよびモバイルアプリケーション向けの開発プラットフォーム

JDKには、help programmers with writing, debugging or maintaining applicationsのツールがたくさん含まれています。 最も人気のあるものは、コンパイラ(javac)、インタプリタ(java)、アーカイバ(jar)、およびドキュメントジェネレータ(javadoc)です。

JREJava Runtime Environmentです。 これはJDKの一部ですが、it contains the minimum functionality to run Java applicationsです。 Java Virtual Machine、コアクラス、およびサポートファイルで構成されます。 たとえば、コンパイラはありません。

JVMは、Java Virtual Machineの頭字語であり、バイトコードにコンパイルされたプログラムを実行できる仮想マシンです。 異なる実装間の相互運用性を確保することが重要であるため、JVM仕様で説明されています。 The most important function of a JVM is to enable users to deploy the same Java application into different operating systems and environments without worrying about what lies underneath

詳細については、Difference Between JVM, JRE, and JDKの記事を確認してください。

Q6. スタックとヒープの違いは何ですか?

すべての変数とオブジェクトがJVMによって保存されるメモリの2つの部分があります。 1つ目はstackで、2つ目はheapです。

stack is a place where the JVM reserves blocks for local variables and additional data。 スタックはLIFO(後入れ先出し)構造です。 これは、メソッドが呼び出されるたびに、ローカル変数とオブジェクト参照用に新しいブロックが予約されることを意味します。 新しいメソッドを呼び出すたびに、次のブロックが予約されます。 メソッドの実行が終了すると、ブロックは開始された逆の方法で解放されます。

すべての新しいスレッドには独自のスタックがあります。

スタックのメモリ領域はヒープよりもはるかに少ないことに注意してください。 また、スタックがいっぱいになると、JVMはStackOverflowErrorをスローします。 悪い再帰呼び出しがあり、再帰が深すぎる場合に発生する可能性があります。

Every new object is created on the Java heap which is used for a dynamic allocation。 若い(保育園)スペースと古いスペースに分けられた未使用のオブジェクトを消去する責任があるgarbage collectorがあります。 ヒープへのメモリアクセスは、スタックへのアクセスよりも遅くなります。 ヒープがいっぱいになると、JVMはOutOfMemoryErrorをスローします。

詳細については、Stack Memory and Heap Space in Javaの記事をご覧ください。

Q7. Comparable インターフェースとComparatorインターフェースの違いは何ですか?

新しいクラスを作成するときに、そのクラスのオブジェクトを比較したい場合があります。 並べ替えられたコレクションを使用する場合に特に役立ちます。 これを行うには、Comparableインターフェイスを使用する方法とComparatorインターフェイスを使用する方法の2つがあります。

まず、Comparableインターフェースを見てみましょう。

public interface Comparable {
    int compareTo(T var1);
}

そのインターフェイスを、オブジェクトをソートするクラスによって実装する必要があります。

compareTo()メソッドがあり、整数を返します。 -1、0、および1の3つの値を返すことができます。これは、このオブジェクトが比較されるオブジェクトより小さい、等しい、または大きいことを意味します。

オーバーライドされたcompareT0()メソッドはequals()メソッドと一致している必要があることに注意してください。

一方、Comparatorインターフェイスを使用できます。 Collectionインターフェースのsort()メソッドに渡すか、並べ替えられたコレクションをインスタンス化するときに渡すことができます。 そのため、主に1回限りの並べ替え戦略を作成するために使用されます。

さらに、Comparableインターフェースを実装していないサードパーティのクラスを使用する場合にも役立ちます。

compareTo()メソッドと同様に、オーバーライドされたcompare()メソッドはequals()メソッドと一致している必要がありますが、オプションでnullとの比較が可能になる場合があります。

詳細については、Comparator and Comparable in Javaの記事をご覧ください。

Q8. voidタイプとは何ですか?いつ使用しますか?

Javaでメソッドを記述するたびに、戻り値の型が必要です。 メソッドが値を返さないようにする場合は、voidキーワードを使用できます。

また、Voidクラスがあることも知っておく必要があります。 これは、たとえばジェネリックスを操作するときに使用できるプレースホルダークラスです。 Voidクラスは、インスタンス化も拡張もできません。

Q9. オブジェクトクラスのメソッドとは何ですか?

Objectクラスに含まれるメソッドと、それらがどのように機能するかを知ることが重要です。 これらのメソッドをオーバーライドする場合にも非常に役立ちます。

  • clone() –このオブジェクトのコピーを返します

  • equals() –このオブジェクトがパラメーターとして渡されたオブジェクトと等しい場合にtrueを返します

  • finalize() –ガベージコレクターは、メモリのクリーニング中にこのメソッドを呼び出します

  • getClass() –このオブジェクトのランタイムクラスを返します

  • hashCode() –このオブジェクトのハッシュコードを返します。 We should be aware that it should be consistent with the equals() method

  • notify() –オブジェクトのモニターを待機している単一のスレッドに通知を送信します

  • notifyAll() –オブジェクトのモニターを待機しているすべてのスレッドに通知を送信します

  • toString() –このオブジェクトの文字列表現を返します

  • wait() –このメソッドには3つのオーバーロードバージョンがあります。 別のスレッドがこのオブジェクトでnotify()またはnotifyAll()を呼び出すまで、現在のスレッドに指定された時間待機させます。

Q10. 列挙型とは何ですか?

Enumは、開発者が事前定義された定数値のセットを指定できるようにするクラスのタイプです。 このようなクラスを作成するには、enumキーワードを使用する必要があります。 曜日の列挙を想像してみましょう。

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

すべての定数を反復処理するには、静的values()メソッドを使用できます。 さらに、列挙型を使用すると、プロパティなどのメンバーや、通常のクラスのようなメソッドを定義できます。

Although it’s a special type of class, we can’t subclass it.ただし、列挙型はインターフェイスを実装できます。

Enumsのもう1つの興味深い利点は、スレッドセーフであるため、シングルトンとして広く使用されていることです。

列挙型の詳細については、one of our guidesを参照してください。

Q11. a JARとは何ですか?

JAR isはJava archiveのショートカットです。 これは、ZIPファイル形式を使用してパッケージ化されたアーカイブファイルです。 これを使用して、アプリケーションに必要なクラスファイルと補助リソースを含めることができます。 多くの機能があります:

  • Security –JARファイルにデジタル署名できます

  • Compression –は、JARの使用中に、効率的なストレージのためにファイルを圧縮できます

  • Portability –複数のプラットフォームで同じJARファイルを使用できます

  • Versioning – JARファイルは、それらに含まれるファイルに関するメタデータを保持できます

  • Sealing –JARファイル内のパッケージを封印できます。 つまり、1つのパッケージのすべてのクラスを同じJARファイルに含める必要があります

  • Extensions – JARファイル形式を使用して、既存のソフトウェアのモジュールまたは拡張機能をパッケージ化できます

Q12. aNullPointerExceptionとは何ですか?

NullPointerExceptionは、おそらくJavaの世界で最も一般的な例外です。 これはチェックされていない例外であるため、RuntimeExceptionを拡張します。 私たちはそれを処理しようとすべきではありません。

この例外は、次の場合のように、変数にアクセスしたり、null参照のメソッドを呼び出したりしようとするとスローされます。

  • null参照のメソッドを呼び出す

  • ヌル参照のフィールドを設定または取得する

  • null配列参照の長さを確認する

  • null配列参照のアイテムを設定または取得する

  • nullを投げる

Q13. Javaの2種類のキャストとは何ですか? キャスト中にどの例外がスローされる可能性がありますか? どうすれば回避できますか?

Javaでは2種類のキャストを区別できます。 We can do upcasting which is casting an object to a supertype or downcasting which is casting an object to a subtype.

Upcastingは非常に単純で、いつでも実行できます。 たとえば、StringインスタンスをObjectタイプにアップキャストできます。

Object str = "string";

または、変数をdowncastすることもできます。 タイプチェックが含まれるため、アップキャストほど安全ではありません。 オブジェクトを誤ってキャストすると、JVMは実行時にClassCastExcpetionをスローします。 Fortunately, we can use the instanceof keyword to prevent invalid casting:

Object o = "string";
String str = (String) o; // it's ok

Object o2 = new Object();
String str2 = (String) o2; // ClassCastException will be thrown

if (o2 instanceof String) { // returns false
    String str3 = (String) o2;
}

型キャストin this articleについて詳しく知ることができます。

3. 上級プログラマ向けのコアJava言語の質問

Q1. 文字列が不変のクラスである理由

Stringオブジェクトは、JVMによって他のオブジェクトとは異なる方法で処理されることを知っておく必要があります。 1つの違いは、Stringオブジェクトは不変であるということです。 It means that we can’t change them once we have created them.そのように動作する理由はいくつかあります。

  1. それらは、ヒープメモリの特別な部分であるstring poolに格納されます。 多くのスペースを節約する責任があります。

  2. Stringクラスの不変性は、そのハッシュコードが変更されないことを保証します。 Due to that fact, Strings can be effectively used as keys in hashing collections.ハッシュコードの変更によってデータが上書きされることはありません。

  3. 複数のスレッドで安全に使用できます。 No thread can change the value of a String object, so we get thread safety for free.

  4. 深刻なセキュリティ問題を回避するために、文字列は不変です。 パスワードなどの機密データは、信頼できないソースまたは別のスレッドによって変更される可能性があります。

文字列in this articleの不変性について詳しく知ることができます。

Q2. 動的バインディングと静的バインディングの違いは何ですか?

Javaでのバインディングは、メソッド呼び出しを適切なメソッド本体に関連付けるプロセスです。 Javaでは、静的と動的の2種類のバインディングを区別できます。

静的バインディングと動的バインディングの主な違いは、静的バインディングはコンパイル時に発生し、動的バインディングは実行時に発生することです。

Static bindingは、バインドにクラス情報を使用します。 privateまたはstaticおよびfinalのメソッドと変数であるクラスメンバーを解決する責任があります。 また、静的バインディングは、オーバーロードされたメソッドをバインドします。

一方、Dynamic bindingは、オブジェクト情報を使用してバインディングを解決します。 そのため、仮想メソッドとオーバーライドされたメソッドを解決する責任があります。

Q3. JITとは

JITは「ジャストインタイム」を表します。 これは、ランタイムで実行され、アプリケーションのパフォーマンスを向上させるJREのコンポーネントです。 Specifically, it’s a compiler which runs just after the program’s start.

これは、アプリケーションが開始されるずっと前にコードをコンパイルする通常のJavaコンパイラとは異なります。 JITはさまざまな方法でアプリケーションを高速化できます。

たとえば、JITコンパイラーは、バイトコードをネイティブ命令にオンザフライでコンパイルして、パフォーマンスを向上させます。 また、ターゲットCPUおよびオペレーティングシステムに合わせてコードを最適化できます。

さらに、最適なパフォーマンスを得るための再コンパイルに使用できる多くのランタイム統計にアクセスできます。 これにより、グローバルなコードの最適化を実行したり、コードを再配置してキャッシュの使用効率を改善したりすることもできます。

Q4. JavaのReflectionとは何ですか?

リフレクションは、Javaの非常に強力なメカニズムです。 リフレクションは、プログラマーが実行時にプログラムの内部状態(プロパティ、メソッド、クラスなど)を検査または変更できるようにするJava言語のメカニズムです。 java.lang.reflectパッケージは、リフレクションを使用するために必要なすべてのコンポーネントを提供します。

この機能を使用すると、クラス定義に含まれるすべての可能なフィールド、メソッド、コンストラクターにアクセスできます。 アクセス修飾子に関係なくアクセスできます。 たとえば、プライベートメンバーにアクセスできることを意味します。 そのために、彼らの名前を知る必要はありません。 私たちがしなければならないのは、Classのいくつかの静的メソッドを使用することです。

リフレクションを介してアクセスを制限する可能性があることを知っておく価値があります。 そのために、JavaセキュリティマネージャとJavaセキュリティポリシーファイルを使用できます。 それらは、クラスにパーミッションを付与することを可能にします。

Java 9以降のモジュールを使用する場合、デフォルトでは、別のモジュールからインポートされたクラスでリフレクションを使用できないことを知っておく必要があります。 他のクラスがリフレクションを使用してパッケージのプライベートメンバーにアクセスできるようにするには、「Reflection」権限を付与する必要があります。

This articleは、JavaReflectionについてさらに詳しく説明します。

Q5. aクラスローダーとは何ですか?

classloaderは、Javaで最も重要なコンポーネントの1つです。 これはJREの一部です。

簡単に言うと、 classloaderはクラスをJVMにロードする役割を果たします。 次の3種類のクラスローダーを区別できます。

  • Bootstrap classloader –コアJavaクラスをロードします。 それらは<JAVA_HOME>/jre/libディレクトリにあります

  • Extension classloader –<JAVA_HOME>/jre/lib/extまたはjava.ext.dirsプロパティで定義されたパスにあるクラスをロードします

  • System classloader –アプリケーションのクラスパスにクラスをロードします

クラスローダーは「オンデマンド」でクラスをロードします。 クラスは、プログラムによって呼び出された後にロードされることを意味します。 さらに、クラスローダーは、指定された名前のクラスを1回だけロードできます。 ただし、同じクラスが2つの異なるクラスローダーによってロードされる場合、それらのクラスは同等性チェックで失敗します。

クラスローダーの詳細については、Class Loaders in Javaの記事をご覧ください。

Q6. 静的クラス読み込みと動的クラス読み込みの違いは何ですか?

静的クラスの読み込みは、コンパイル時にソースクラスを使用できる場合に行われます。 newキーワードを使用してオブジェクトインスタンスを作成することで、これを利用できます。

動的クラス読み込みとは、コンパイル時にクラス定義を提供できない状況を指します。 それでも、実行時にそれを行うことができます。 クラスのインスタンスを作成するには、Class.forName()メソッドを使用する必要があります。

Class.forName("oracle.jdbc.driver.OracleDriver")

Q7. Serializableインターフェースの目的は何ですか?

We can use the Serializable interface to enable serializability of a class, using Java’s Serialization API.シリアル化は、オブジェクトの状態をバイトシーケンスとして保存するメカニズムであり、逆シリアル化は、オブジェクトの状態をバイトシーケンスから復元するメカニズムです。 シリアル化された出力には、オブジェクトの状態と、オブジェクトのタイプおよびそのフィールドのタイプに関するいくつかのメタデータが保持されます。

直列化可能クラスのサブタイプも直列化可能であることを知っておく必要があります。 ただし、クラスをシリアル化可能にしたいが、そのスーパータイプがシリアル化可能でない場合は、2つのことを行う必要があります。

  • Serializableインターフェースを実装する

  • スーパークラスに引数なしのコンストラクタが存在することを保証する

シリアル化の詳細については、one of our articlesを参照してください。

Q8. Javaにデストラクタはありますか?

Javaでは、ガベージコレクターは未使用のオブジェクトを自動的に削除してメモリを解放します。 開発者は、オブジェクトを削除対象としてマークする必要がありません。これはエラーを起こしやすいです。 So it’s sensible Java has no destructors available.

オブジェクトが開いているソケット、開いているファイル、またはデータベース接続を保持している場合は、the garbage collector is not able to reclaim those resourcesclose methodでリソースを解放し、try-finally syntaxを使用して、後でJava 7の前にI / OクラスFileInputStreamFileOutputStreamなどのメソッドを呼び出すことができます。 As of Java 7, we can implement interface AutoCloseable and use try-with-resources statement to write shorter and cleaner code。 ただし、APIユーザーがclose methodの呼び出しを忘れる可能性があるため、finalize methodとCleaner classがセーフティネットとして機能するようになります。 But please be cautioned they are not equivalent to the destructor.

It’s not assured both the finalize method and Cleaner class will run promptly. JVMが終了する前に実行する機会さえありません。 System.runFinalization を呼び出して、JVMがファイナライズ待ちのオブジェクトのfinalize メソッドを実行することを提案することはできますが、それでも決定論的ではありません。

さらに、finalizeメソッドは、パフォーマンスの問題やデッドロックなどを引き起こす可能性があります。 記事の1つであるA Guide to the finalize Method in Javaを見ると、より多くの情報を見つけることができます。

As of Java 9Cleaner class is added to replace the finalize methodには、欠点があるためです。 その結果、クリーニングアクションを実行するスレッドをより適切に制御できます。

ただし、Java仕様では、System.exit is実装固有のクリーナーの動作が指摘されており、Javaはクリーニングアクションが呼び出されるかどうかを保証しません。