前の 2 つの記事では、面接でよく聞かれる重要な質問について説明しました。次に進み、残りの質問を見てみましょう。
深いコピーと浅いコピー
オリジナルの正確なコピーがそのクローンです。Java では、これは、元のオブジェクトと同様の構造を持つオブジェクトを作成できることを意味します。このメソッドはclone()
この機能を提供します。浅いコピーでは、できるだけ少ない情報をコピーします。デフォルトでは、Java でのクローン作成は浅いものです。Object class
コピーしているクラスの構造については知りません。クローン作成時に、JVM は次のことを実行します。
- クラスにプリミティブ型のメンバーのみが含まれる場合、オブジェクトの完全に新しいコピーが作成され、そのオブジェクトへの参照が返されます。
- クラスにプリミティブ型のメンバーだけでなく、他のクラス型のメンバーも含まれる場合、これらのクラスのオブジェクトへの参照がコピーされます。したがって、両方のオブジェクトは同じ参照を持つことになります。
- プリミティブ データを個別にコピーする必要はありません。
- 元のクラスのすべてのメンバー クラスはクローン作成をサポートする必要があります。クラス メンバーごとに、
super.clone()
メソッドがオーバーライドされるときにそれを呼び出す必要がありますclone()
。 - クラスのメンバーがクローン作成をサポートしていない場合は、 clone メソッドでそのクラスの新しいインスタンスを作成し、そのクラスの各メンバーをすべての属性とともに新しいクラス オブジェクトに一度に 1 つずつコピーする必要があります。
同期とは何ですか? オブジェクトレベルのロックとクラスレベルのロック?
同期とはマルチスレッドを指します。同期されたコード ブロックは、一度に 1 つのスレッドによってのみ実行できます。Java を使用すると、複数のスレッドを同時に処理できます。これにより、2 つ以上のスレッドが同じフィールドにアクセスしようとする可能性があります。同期は、メモリ リソースが不適切に使用されたときに発生するメモリ エラーを回避するのに役立ちます。メソッドが同期済みとして宣言されると、スレッドはそのモニターを保持します。この時点で別のスレッドが同期されたメソッドにアクセスしようとすると、スレッドはブロックされ、モニターが解放されるまで待機します。Java での同期は、特別なsynchronizedキーワードを使用して実現されます。この方法で、クラス内の個々のブロックまたはメソッドをマークできます。synchronized キーワードは、クラス変数または属性と組み合わせて使用することはできません。 オブジェクト レベルのロックは、非静的メソッドまたは非静的コード ブロックを同期して、クラスの特定のインスタンスで 1 つのスレッドだけがコード ブロックを実行できるようにするメカニズムです。これは、クラス インスタンスをスレッドセーフにするために常に実行する必要があります。 クラスレベルのロックにより、複数のスレッドがクラスの使用可能なすべてのインスタンスの同期ブロックに入ることを防ぎます。たとえば、DemoClass クラスのインスタンスが 100 個ある場合、変数の 1 つを使用して demoMethod() を実行できるスレッドは一度に 1 つだけになります。これは、静的なスレッドの安全性を確保するために常に実行する必要があります。 同期について詳しくは、こちらをご覧ください。sleep() と wait() の違いは何ですか?
Sleep()
プロセスを数秒遅らせるために使用されるメソッドです。の場合、スレッドはまたはメソッドwait()
を呼び出すまで待機状態になります。主な違いは、モニターのロックは解除しますが、ロックは解除しないことです。マルチスレッド アプリケーションに使用され、単にスレッドの実行を一時停止するために使用されます。 現在のスレッドを一定時間「実行不可」状態にします。スレッドは、このメソッドが呼び出される前のモニターの状態を保存します。別のスレッドが を呼び出すと、「眠った」スレッドが目覚めます。これは静的メソッドであることに注意してください。つまり、常に現在のスレッド (メソッドを実行しているスレッド) に影響します。よくある間違いは、別のスレッドがどこにあるかを呼び出すことです。メソッドを呼び出した現在のスレッドがスレッド でない場合でも。と同様に、現在のスレッドをしばらくの間「実行不可」状態にしますが、若干のニュアンスがあります。スレッドではなくオブジェクトで呼び出されます。このオブジェクトを「ロック オブジェクト」と呼びます。を呼び出す前に、現在のスレッドを「ロック オブジェクト」と同期する必要があります。その後、このロックを解放し、このロックに関連付けられた「待機リスト」にスレッドを追加します。後で、別のスレッドが同じロック オブジェクトと同期し、 を呼び出すことができます。このメソッドは、まだ待機している元のスレッドを「ウェイクアップ」します。原則として、/ は/と比較できます。アクティブなスレッドのみがスリープ状態のスレッドへの直接ポインタを必要とせず、共有ロック オブジェクトを知る必要があるだけです。 詳しい違いについては、こちらをお読みください。notify()
notifyAll()
wait()
sleep()
Wait()
sleep()
Thread.sleep()
t.interrupt()
sleep()
sleep()
t.sleep()
t
sleep()
t
Object.wait()
sleep()
Wait()
lock.wait()
wait()
lock.notify()
wait()
notify()
sleep()
interrupt()
これにnullを参照変数に代入することは可能でしょうか?
いいえ、あなたがすることはできません。Java では、代入演算子の左側は変数でなければなりません。「This」は、常にクラスの現在のインスタンスを示す特別なキーワードです。それは単なる変数ではありません。同様に、「super」キーワードまたはその他の同様のキーワードを使用して変数に null を割り当てることはできません。&& と & はどう違いますか?
&
- ビットごとに&&
- 論理的に。
&
操作の両側を評価します。&&
演算の左側を評価します。true の場合、右側の評価が続行されます。
equals() メソッドと hachCode() メソッドをオーバーライドするにはどうすればよいですか?
hashCode()
およびメソッドは、Java オブジェクトの親クラスであるequals()
class で定義されます。Object
このため、すべての Java オブジェクトはメソッドのデフォルト実装を継承します。このメソッドは、hashCode()
特定のオブジェクトの一意の整数を取得するために使用されます。この整数は、オブジェクトを に保存する必要がある場合に、そのオブジェクトの場所を決定するために使用されますHashTable
。デフォルトでは、オブジェクトが保存されているメモリ位置のアドレス表現をhashCode()
返します。integer
メソッド はequls()
、その名前が示すように、2 つのオブジェクトが等しいかどうかを単純にテストするために使用されます。デフォルトの実装では、オブジェクト参照が等しいかどうかをチェックします。以下は、これらのメソッドをリロードするための重要なガイドラインです。
hashCode()
と を生成するときは、常に同じオブジェクト属性を使用してくださいequals()
。- 対称。それらの。一部のオブジェクトに対してtrue を
x
返す場合はy
x.equals(y)
、y.equals(x)
true を返す必要があります。 - 反射性。どのオブジェクトでも
x
x.equals(x)
true を返さなければなりません。 - 一貫性。どのオブジェクトに対しても、比較に使用される情報が変更されない場合は同じものを返します
x
。y
x.equals(y)
- 推移性。オブジェクトおよびについて
x
、true を返し、true を返す場合はtrue を返す必要があります。y
z
x.equals(y)
y.equals(z)
x.equals(z)
- アプリケーションの実行中に同じオブジェクトに対してメソッドが呼び出されるときは、使用される情報が変更されない限り、同じ番号が返される必要があります。
hashCode
異なるアプリケーション インスタンス内の同一のオブジェクトに対して異なる値を返すことができます。 - によれば、2 つのオブジェクトが等しい場合
equals
、それらはhashCode
同じ値を返さなければなりません。 - 逆の要件はオプションです。2 つの等しくないオブジェクトは同じ hashCode を返す可能性があります。ただし、パフォーマンスを向上させるには、異なるオブジェクトが異なるコードを返すようにすることをお勧めします。
アクセス修飾子について教えてください
Java クラス、フィールド、コンストラクター、およびメソッドには、次の 4 つの異なるアクセス修飾子のいずれかを指定できます。 private メソッドまたは変数がprivate とマークされている場合、同じクラス内のコードのみが変数にアクセスしたり、メソッドを呼び出したりできます。サブクラス内のコードは変数やメソッドにアクセスできず、他のクラスからもアクセスできません。private アクセス修飾子は、コンストラクター、メソッド、変数に最もよく使用されます。 デフォルトのアクセス 修飾子は、修飾子がまったく指定されていない場合に宣言されます。この修飾子は、特定のクラスのフィールド、コンストラクター、およびメソッドへのアクセスが、クラス自体内のコード、つまり同じパッケージ内のクラス内のコードによって取得できることを意味します。サブクラスは、サブクラスがスーパークラスと同じパッケージ内にない限り、 defaultとして宣言されている場合、スーパークラスのメソッドおよびメンバー変数にアクセスできません。protected protected 修飾子は、サブクラスもスーパークラスの protected メソッドおよび変数にアクセスできる点を除いて、defaultと同じように機能します。このステートメントは、サブクラスがスーパークラスと同じパッケージ内にない場合でも当てはまります。 public public アクセス修飾子は、コードがどこにあるかに関係なく、すべてのコードがクラス、その変数、コンストラクター、またはメソッドにアクセスできることを意味します。ガベージコレクターとは何ですか? 彼に電話してもいいですか?
ガベージ コレクションは、Java や NET.Framework の言語など、多くの最新のプログラミング言語における自動メモリ管理の機能です。ガベージ コレクションを使用する言語は、多くの場合、JVM などの仮想マシンでガベージ コレクションを解釈します。ガベージ コレクションには 2 つの目的があります。1 つは未使用のメモリを解放すること、もう 1 つはプログラムがメモリをまだ使用している場合はメモリを解放しないことです。ガベージコレクションを手動で実行できますか? いいえ、System.gc()
可能な限り多くのアクセスが提供されます。最良のオプションは、メソッドを呼び出すことですSystem.gc()
。これにより、ガベージ コレクターに実行する必要があることが通知されます。ガベージ コレクターは非決定的であるため、すぐに実行する方法はありません。さらに、ドキュメントによると、OutOfMemoryError
仮想マシンがフル ガベージ コレクション後にメモリの解放に失敗した場合、転送されません。 ガベージ コレクターの詳細については、こちらをご覧ください。
ネイティブキーワードとはどういう意味ですか? 詳しく説明してください
ネイティブキーワードは、メソッドが Java ファイル以外のプログラミング言語で実装されていることを示すために使用されます。 過去にはネイティブメソッドが使用されてきました。Java の現在のバージョンでは、これが必要になることはあまりありません。現在、ネイティブ メソッドは次の場合に必要です。- 別の言語で書かれたライブラリを Java から呼び出す必要があります。
- 別の言語 (通常は C) を使用してのみアクセスできるシステムまたはハードウェア リソースにアクセスする必要があります。実際、実際のコンピュータ (ディスクやネットワーク データなど) と対話する多くのシステム関数は、ネイティブ メソッドによってのみ呼び出すことができます。
- JNI/JNA は、特に複雑なことを実行しようとすると、JVM を不安定にする可能性があります。ネイティブ メソッドが間違った動作をすると、JVM がクラッシュする可能性があります。また、ネイティブ メソッドが複数のスレッドから呼び出された場合、悪いことが起こる可能性があります。等々。
- ネイティブコードを使用してプログラムをデバッグするのはさらに困難です。
- ネイティブ コードにはフレームワークを個別に構築する必要があるため、他のプラットフォームへの移植時に問題が発生する可能性があります。
シリアル化とは何ですか?
コンピューター サイエンスでは、データの保存と送信のコンテキストにおいて、シリアル化は、データ構造またはオブジェクトの状態を、保存して後で別のコンピューティング環境で取得できる形式に変換するプロセスです。一連のビットを受信した後、シリアル化形式に従って再計算され、元のオブジェクトの意味的に同一のクローンを作成するために使用できます。Java は自動シリアル化を提供します。これには、オブジェクトがインターフェイスを実装する必要がありますjava.io.Serializable
。インターフェイス実装は、クラスを「直列化可能」としてマークします。java.io.Serializable インターフェースにはシリアル化メソッドはありませんが、シリアル化可能クラスは、シリアル化/逆シリアル化プロセスの一部として呼び出されるメソッドをオプションで定義できます。クラスに変更を加える場合は、どのクラスがシリアル化と互換性があるのか、どのクラスが互換性がないのかを考慮する必要があります。完全な手順はここで読むことができます。最も重要な点を説明します: 互換性のない変更:
- フィールドを削除します。
- クラスを階層内で上下に移動します。
- 非静的フィールドを静的フィールドに、または非一時的フィールドを一時的フィールドに変更します。
- 宣言されたプリミティブ データ型を変更する。
- デフォルトでフィールドの書き込みまたは読み取りが行われないように
WriteObject
メソッドを変更します。ReadObject
Serializable
へのクラス変更Externalizable
、またはその逆のクラス変更。- enumクラスを非 enumクラスに変更する、またはその逆の変更。
Serializable
またはExternalizable
;を削除します。- クラスにメソッド
writeReplace
を追加します。readResolve
- フィールドの追加;
- クラスの追加/削除。
- メソッドの追加
WriteObject/ReadObject
[メソッドdefaultReadObject
またはdefaultWriteObject
最初に呼び出す必要があります]; - メソッドの削除
WriteObject/ReadObject
; - 追加
java.io.Serializable
; - フィールドアクセスの変更。
- 静的フィールドを非静的フィールドに変更するか、一時的フィールドを非一時的フィールドに変更します。
GO TO FULL VERSION