Android 中級および上級開発面接の質問スプリント コレクション (1)

以下は、主に過去に収集されたインタビューの質問を分類およびソートするためのものであり、誰もが確認および参照するのに便利です。今日は第1話〜

強調: [ 因篇幅问题:文中只放部分内容,全部文档需要的可找作者获取。]

Java の基本

1.抽象クラスとインターフェースの違いは何ですか?

参考回答:一般的な違いは次のとおりです。

  • 抽象クラスはメンバー メソッドの実装の詳細を提供できますが、パブリック抽象メソッドのみがインターフェイスに存在できます。
  • 抽象クラスのメンバー変数はさまざまな型にすることができますが、インターフェイスのメンバー変数はpublic static final型。
  • インターフェイスには、コンストラクター、静的コード ブロック、および静的メソッドを含めることはできませんが、抽象クラスには、コンストラクター、静的コード ブロック、および静的メソッドを含めることができます。
  • クラスは 1 つの抽象クラスしか継承できませんが、クラスは複数のインターフェイスを実装できます。
  • インターフェースはクラスに実装されているメソッドを見つけるのに時間がかかるため、抽象クラスはインターフェースよりも高速にアクセスできます。
  • 抽象クラスに新しいメソッドを追加する場合、デフォルトの実装を提供できます。したがって、現在のコードを変更する必要はありません。メソッドをインターフェイスに追加する場合は、インターフェイスを実装するクラスを変更する必要があります。
  • インターフェイスはクラスの動作を制限するためのものであり、デカップリングに使用できますが、抽象クラスはコードの再利用に重点を置いています。

2. final、static、synchronized で変更できるものと、変更後の役割について話しますか?

参考回答: 最終: クラス、メソッド、およびフィールドを変更できます。

修饰类:该类不会被继承。
​
修饰方法:该方法不能被重写。
​
修饰字段:被修饰的 字段必须 赋初始值,并且不能被改变。如果字段是引用类型的。那么他将不能引用别的对象,但是当前的对象内的属性值是可以改变的。

static : 内部クラス、メソッド、フィールドを変更できます。

修饰内部类:被static修饰 的内部类可以直接作为一个 普通的类来使用,而不需先实例一个外部列。
​
修饰方法:调用该方法的时候只需要类名 . 方法就可以直接调用,不需要创建对象。
​
修饰字段:通过类名 . 的方式可以直接 获取 或者 赋值。

同期はメソッド、コード ブロックを変更できます

修饰方法:被 synchronized 修饰方法方法在同一时刻只能被一个线程访问。其他线程将会被阻塞,直到当前线程释放锁。
​
修饰代码块:其实和修饰方法差不多,只不过 修饰代码块可以 使用 类锁。方法如果要使用类锁,只能设置为静态的方法。

3. String、StringBuffer、StringBuilder の違いを簡単に説明してください。

参考回答:

String は文字列定数です。一度作成すると変更できず、スレッド セーフです。String クラスは final 修飾子を使用し、継承できません。String の長さは変更されません。少数の操作に適した文字列。StringBuffer は、可変長でスレッド セーフな文字列変数です。マルチスレッドでの文字バッファでの多数の文字列操作に適しています. StringBuilder は文字列変数であり, 長さは可変であり, スレッドは安全ではありません. これは、1 つのスレッドで文字バッファー内の多数の文字列操作に適しています。文字列操作は高速で実行されます: StringBuilder > StringBuffer > String

  1. 「equals」「==」「hashCode」の違いと使い方は?

参考回答:

  • : == は、変数に対応するメモリに格納された値が同じかどうかを比較するために使用されます. 2 つの基本型 (基本型であることに注意してください) のデータを比較したり、2 つの参照変数が等しいかどうかを比較したりするには、次のことができます。のみ使用オペレーター。変数が指すデータが Objet obj 1= new Object() などのオブジェクト型の場合、変数 obj1 は 1 つのメモリであり、new Object() は別のメモリ (ヒープ メモリ) です。 )、変数 obj1 に対応するメモリに格納されている値は、オブジェクトが占有するメモリ (ヒープ メモリ) の最初のアドレスです。オブジェクト型を指す変数の場合、2 つの変数が同じオブジェクトを指すかどうかを比較する場合、つまり、2 つの変数に対応するメモリ内の値が等しいかどうかを確認する場合は、次を使用する必要があります比較する == 演算子。
  • equals: equals メソッドは、2 つの独立したオブジェクトの内容が同じかどうかを比較するために使用されます。
String a=new String("a");
String b=new String("a");

The two new statement create two objects, and then use the two variables a/b to point to one of the objects each each. これらは 2 つの異なるオブジェクトであり、それらの最初のアドレスは異なります。 b. (対応するオブジェクトの最初のアドレス) が同じでないため、式 a==b は false を返し、2 つのオブジェクトの内容が同じであるため、式 a.equals(b) は true を返します。 . 同等のソース コードを見てみましょう。

 * Note that it is generally necessary to override the {@code hashCode}
 * method whenever this method is overridden, so as to maintain the
 * general contract for the {@code hashCode} method, which states
 * that equal objects must have equal hash codes.
   *
 * @param   obj   the reference object with which to compare.
 * @return  {@code true} if this object is the same as the obj
 * argument; {@code false} otherwise.
 * @see     #hashCode()
 * @see     java.util.HashMap
   */
   public boolean equals(Object obj) {
   return (this == obj);
   }

クラスが equals メソッドをオーバーライドしない場合、オブジェクトの equals の呼び出しは実際には == です。

  • hashCode: 書き換えられた equals() は一般的により包括的で複雑であるため、効率は比較的低く、比較に hashCode() を使用すると、比較用のハッシュ値を生成するだけでよく、効率が非常に高いため、hashCode () 効率が非常に高いのに、なぜ equals() が必要なのですか?
  • 使用シナリオ: hashCode() は完全に信頼できるわけではなく、異なるオブジェクトによって生成されたハッシュコードが同じになる場合があるため (ハッシュの競合)、hashCode() はほとんどの場合信頼できるとしか言えず、完全に信頼できるわけではありません。 Out を得ることができます: equals() である 2 つのオブジェクトは等しく、それらの hashCode() は等しい必要があります。つまり、equals() との比較は完全に信頼できます。hashCode() が等しい 2 つのオブジェクトの equals() は必ずしも等しいとは限りません。つまり、hashCode() は完全に信頼できるわけではありません。大量かつ高速を必要とするすべての比較に equals() を使用するのは明らかに非効率的であるため、比較する必要がある場合は常に hashCode() を使用して最初に比較することを解決します。 2 つのオブジェクトが明らかに等しくない (つまり、equals() を使用して再度比較する必要がない) hashCode() が同じ場合は、この時点で equals() を比較します。も同じです。これは、2 つのオブジェクトが実際には同じであることを意味します。

5. Java のディープ コピーとシャロー コピーの違いは何ですか?

参考回答:

まず、浅いコピーと深いコピーの両方が既存のオブジェクトに対する操作であることを理解する必要があります。まず、浅いコピーと深いコピーの概念を見てみましょう。Java には、基本的なデータ型 (メタタイプ) に加えて、クラスのインスタンス オブジェクトの参照データ型もあります。また、代入操作には一般に「=」記号を使用します。基本的なデータ型の場合、その値は実際にコピーされますが、オブジェクトの場合、割り当てられるのはオブジェクトの参照のみであり、元のオブジェクトの参照が渡され、実際には同じオブジェクトを指します。

これに基づいて、浅いコピーと深いコピーが区別されます. オブジェクトをコピーするときに、基本データ型のみがコピーされ、参照データ型は参照によってのみ渡され、実際には作成されない場合. 新しいオブジェクトは浅いコピーと見なされます. . 逆に、参照データ型をコピーすると、新しいオブジェクトが作成され、その中のメンバー変数がコピーされます。これはディープ コピーと見なされます。したがって、いわゆる浅いコピーと深いコピーは、オブジェクトをコピーするときに、クラスのインスタンス オブジェクトの参照データ型に対する異なる操作であることを理解する必要があります。

結論として:

1. 浅いコピー:基本データ型を値渡しし、参照データ型を参照コピーする浅いコピーです。

2. ディープ コピー: 基本データ型の値を渡し、参照データ型の新しいオブジェクトを作成し、その内容をコピーします。これがディープ コピーです。

6.エラーと例外の違いについて教えてください。

参考回答:

エラーは、予測不可能なシステムのエラーであり、このような例外が発生すると、プログラムはすぐにクラッシュします。エラーが出ないようにコードを修正しただけでは、この種のエラーはキャッチできません。

例外が予想されます。プログラム内で、特定のコードで例外が発生する可能性があると感じた場合は、try catch を使用してそれをキャッチするか、直接例外をスローすることができます。例外は、コンパイル時例外 (CheckedException) と実行時例外 (RuntimeException) に分けることができます。ランタイム例外はキャプチャ操作 (RuntimeException) を無視でき、コンパイル時例外は try catch を使用してキャッチする必要があります。

7.反射メカニズムとは? リフレクション メカニズムの適用シナリオは何ですか?

参考回答:

Java リフレクション メカニズムは、実行状態では、任意のクラスについて、このクラスのすべてのプロパティとメソッドを知ることができ、任意のオブジェクトについて、そのメソッドとプロパティのいずれかを呼び出すことができるというものです; この動的に取得された情報と動的なオブジェクトのメソッドを呼び出すことを Java 言語のリフレクション機構と呼びます。アプリケーション シナリオ:

  1. 逆コンパイルなどのリバース コード
  2. Retrofit などのアノテーションと組み合わせたフレームワーク
  3. EventBus (イベントバス) などの単純なリフレクション機構のアプリケーション フレームワーク
  4. Gson などのクラス フレームワークを動的に生成する

8. equals() メソッドをオーバーライドする方法について教えてください。hashCode() を書き直す理由

参考回答:

equals: 2 つのオブジェクトのアドレスが等しいかどうかを比較します

hashCode: 通常、hashMap などのコレクションで使用され、要素を格納するときにハッシュ値が最初に計算され、次に要素の場所がハッシュ値に従って決定されます。任意のオブジェクトで hashCode を呼び出すと、返されるハッシュ 値は等しくなければなりません。

なぜhashCodeを書き直す必要があるのですか

要素をコレクションに格納する場合は、最初に hashCode の値を取得し、hashCode が書き換えられていない場合は、要素のアドレスを直接整数に変換して返します。2 つのオブジェクトを作成すると、2 つのオブジェクトのすべての属性値が同じになります。HashSet に格納する場合、最初の要素が直接格納され、2 番目で取得したハッシュ値が 1 番目とは異なるため、2 番目はjdk はデフォルトで異なる hashCode 値を使用するため、各要素も格納されます。equals は false を返す必要があります。したがって、両方の値が保存されます。ただし、これら 2 つのオブジェクトの属性値は同じであるため、データの非一意性が発生します。したがって、一般的に equals を書き換えた後は、hashCode を書き換える必要があります。

メモリリークの問題

equals と hashCode の両方をオーバーライドして、異なるプロパティ値を持つ 2 つのオブジェクトを作成するクラスを想像してみてください。次に、それらはすべて HashSet に格納されます。次に、2 番目の要素の値を変更します。最後に、セット コレクションから 2 番目の要素を削除します。削除した後、繰り返し印刷すると、2 番目の要素が削除されていないことがわかります。要素を削除すると hashCode 値が取得されるのですが、属性値が変更されているため、取得したハッシュ値が保存時に取得したものと異なるため、検索が空になり、jdk はオブジェクトが存在しないと見なします。削除操作が実行されましたが、ユーザー タスク オブジェクトが削除されたため、オブジェクトを長時間解放できず、メモリ リークが発生しました。解決策は、実行中に HashCode 値に関連するオブジェクト情報を変更しないことです。変更する必要がある場合は、最初にコレクションから削除し、データを更新した後にコレクションに追加する必要があります。

要約:

1.hashCode是为了提高在散列结构存储中查找的效率,在线性表中没有作用 
​
2.equals和hashCode需要同时覆盖。 
​
3.若两个对象equals返回true,则hashCode一定返回相同的int数。 
​
4.若两个对象equals返回false,则hashCode不一定返回不同的int数,但为不相等的对象生成不同hashCode值可以提高 哈希表的性能 
​
5.若两个对象hashCode返回相同int数,则equals不一定返回true。 
​
6.若两个对象hashCode返回不同int数,则equals一定返回false。 
​
7.同一对象在执行期间若已经存储在集合中,则不能修改影响hashCode值的相关信息,否则会导致内存泄露问题。 

9. Java の IO ストリームのタイプは何ですか? それらの違いは何ですか?

参考回答:

IO ストリームはいくつかに分割されます

Java には 2 種類のストリームがあり、1 つはバイト ストリーム、もう 1 つは文字ストリームであり、4 つの抽象クラスで表されます (各ストリームには入力と出力が含まれるため、合計で 4 つになります): InputStream、OutputStream 、Reader、Writer . Java のさまざまな変更の他のストリームは、それらから派生しています。

文字ストリームとバイトストリームは、処理データの違いにより区別されます。バイト ストリームは 8 ビットに従って送信されます. バイト ストリームは最も基本的なものです. すべてのファイルのストレージはバイトのストレージです. ファイルの文字はディスク上に予約されていませんが, 文字は最初にバイトにエンコードされます. 、これらのバイトをディスクに保存します。

  • 1. バイト ストリームは、バイナリ オブジェクトを含む任意のタイプのオブジェクトに使用できますが、文字ストリームは文字または文字列のみを処理できます。
  • 2. スロットリングは、あらゆるタイプの IO 操作を処理する機能を提供しますが、Unicode 文字を直接処理することはできませんが、文字ストリームは処理できます。

txt ファイルなどのテキストを読み取るときは、文字ストリームを使用します。mp3 などの非テキスト ファイルを読み取る場合は、バイト ストリームを使用します。理論上はバイトストリームならどんなファイルでも読み込めるのですが、テキストデータを読み込んだ場合、テキストに戻すには変換処理が必要で、相対的に言えば文字ストリームならこの手間が省けるので直接読み込める方法があります.

文字ストリーム処理単位は 2 バイトの Unicode 文字で、それぞれ文字、文字配列、または文字列を操作しますが、バイト ストリーム処理単位は 1 バイトで、バイトおよびバイト配列を操作します。したがって、文字ストリームは、バイトを 2 バイトの Unicode 文字に変換する Java 仮想マシンによって形成されるため、複数の言語のサポートが向上します。

BIO、NIO、AIOの違いは何ですか

BIO: ブロック IO 同期ブロッキング IO は、私たちが通常使用する伝統的な IO であり、シンプルで便利なモードと低い同時処理能力が特徴です。NIO: Non IO synchronous non-blocking IO is a upgrade of a traditional IO. クライアントとサーバーは Channel (チャネル) を介して通信し、多重化を実現します。AIO: Asynchronous IO is a upgrade of NIO, also called NIO2, which implements asynchronous non-blocking IO. 非同期 IO の操作は、イベントとコールバック メカニズムに基づいています。

BIO は接続スレッドです。NIO は、リクエストごとに 1 つのスレッドです。AIO は、事実上、要求ごとに 1 つのスレッドです。

  • BIO: 同期とブロック、サーバーの実装モードは 1 つの接続と 1 つのスレッド、つまり、クライアントが接続要求を持っている場合、サーバーは処理のためにスレッドを開始する必要があります.接続が何もしない場合、不要な原因になりますスレッド オーバーヘッド スレッド プール メカニズムが改善されました。
  • NIO: 同期ノンブロッキング、サーバー実装モードは 1 つの要求と 1 つのスレッドです。つまり、クライアントから送信された接続要求はマルチプレクサーに登録され、マルチプレクサーは I/ O request.処理用スレッド。
  • AIO: 非同期ノンブロッキング、サーバー実装モードは 1 つのスレッドに対して 1 つの有効な要求であり、クライアントの I/O 要求は OS によって最初に完了され、次に処理のためにスレッドを開始するようにサーバー アプリケーションに通知されます。

該当するシナリオ分析

  • BIO方式は接続数が比較的少なく固定数の構成に適している.この方式はサーバリソースの要求が比較的高く,同時実行性はアプリケーションに限定される.JDK1.4以前では唯一の選択肢であった.プログラムは直感的で理解しやすいです。
  • NIO方式は、同時実行性がアプリケーションに限定され、プログラミングがより複雑な、チャットサーバーなど、接続数が多く、接続が比較的短い(動作が軽い)アーキテクチャに適しており、JDK1.4でサポートが開始されました。
  • AIO方式は、フォトアルバムサーバーのように接続数が多く、接続時間が比較的長い(重い処理を行う)アーキテクチャで使用されます.OSをフルコールして同時処理に参加するため、プログラミングが複雑になります.JDK7でサポートを開始しました.それ。

10. Java ジェネリックにおける型消去についての理解と、その制限について話してください。

参考回答:

1: コンパイル中に型消去が発生します。これは、すべての一般的な情報が消去されることを意味します (デフォルトで Object を継承します)。

2: 解決された制限事項: 1 ArrayList(String> は Integer 型のデータを追加できません。コンパイラは最初にコード内のジェネリック型の型をチェックして解決します 2 エディターは ArrayList(String> のジェネリック型から値を取得し、どちらも Object String 3 を強制的に変換する 親クラスがジェネリック型を定義し、サブクラスがそれを実装する; 実装のオーバーロードは、実際にはコンパイラがオーバーライドになります. コンパイラのブリッジメソッドによって解決されます.

3: 未解決の制限: 1) ジェネリック型変数を基本データ型にすることはできません 2) 実行時に型を検出できません; 例: object instanceof ArrayList (String> This logic cannot be implemented 3) ジェネリック型は static used では使用できませんメソッドと静的変数で; 次のように:

public class TestClass {
public static T getSome() {
return null;
}
}

このロジックに static フィールドを追加すると、コンパイラはエラーを報告します

11. String が不変であるように設計されているのはなぜですか?

参考回答:

1: 文字列定数プールが必要

String オブジェクトを作成するとき、文字列が定数プールに既に存在する場合、新しいオブジェクトは作成されませんが、既存のオブジェクトが参照されます。

変更を許すと、あるオブジェクトを変更すると別の独立したオブジェクトに影響を与えるなど、さまざまな論理エラーが発生します. 厳密に言えば、この定数プールのアイデアは最適化方法です.

2: String オブジェクトが HashCode をキャッシュできるようにする

Java の String オブジェクトのハッシュ コードは、hashMap などでよく使用されます。文字列の不変性により、ハッシュ コードの一意性が保証されるため、安全にキャッシュできます。これも最適化です。つまり、新しいハッシュ コードを計算する必要はまったくありません。String クラスには、ハッシュコードをキャッシュするためのプライベート int ハッシュがあります。

3: セキュリティ

文字列は、ネットワーク URL、ファイル パス パスなど、多くのクラスでパラメーターとして使用されます。文字列が固定されていないと、さまざまなセキュリティ リスクが発生します。

12. Java アノテーションの理解度について教えてください。

参考回答:

本質: マークを作成し、このマークを介してコード仕様と変数値にいくつかの変更を加えます。主に3つのカテゴリーに分けられます

ソース .java ファイルにのみ存在し、.class ファイルにコンパイルされて姿を消しました。役割は、開発者がアノテーションの仕様に従ってコードを記述できるようにすることです。例: @OverRide
クラス プリコンパイル期間のプロセスでは、ネイティブ コードの効率とほぼ同じである .class コンテンツに処理されます。役割は、.class ファイルを自動的に生成し、いくつかの補助的な作業を行うことです。例: ButterKnife、GreenDao、ARouter ネイティブコードに匹敵する効率性
ランタイム .class ファイルにコンパイルした後も、注釈の形式で存在します。代わりに、実行時に有効になります。役割は次のとおりです。実行時に、リフレクションを通じていくつかの補助的な作業を行います。例: トラバーサルとリフレクションを集中的に使用するため、効率が低下します。また、9.0 ではリフレクションを無効にします

13. Java メンバー変数、ローカル変数、静的変数の作成とリサイクルのタイミングについて教えてください。

参考回答:

メンバ変数: ライフサイクルにはクラスオブジェクトが伴う. クラスオブジェクトが再利用されるとヒープに格納される. 静的変数: 再利用されない. メソッド領域では, クラスのロードとともにロードされ, で消える.クラスの消滅. クラスは長期間使用されない必要があるため, 使用されていないか関連付けられていない場合, リサイクルメカニズムによって再利用される可能性があるため, 静的メンバ変数のライフサイクルは非常に長い. そうでない限り.共有データ、静的の使用はお勧めしません。リサイクル可能なものはスタックに格納されます。

おすすめ

転載: blog.csdn.net/m0_64420071/article/details/127215833