「Java In-Depth Analysis」という本を見つけました。これには、私が普段気に留めていない多くの誤解が含まれています。開発中には使用されないかもしれませんが、これらの概念は曖昧であってはなりません。この本の内容は今でも非常に役に立ちます。ここにいくつかの要約メモを記載します。
1. Java には goto ステートメントはありません。 goto ステートメントを多用するとプログラムの可読性と保守性が低下するため、Java 言語では goto の使用が中止されました。同時に、プログラマが独自に goto を使用することによる混乱を避けるために、Java 言語では goto をキーワードとして定義していますが、構文は定義していないため、「予約語」と呼ばれます。
2 true、false、nullはIDE上で色分けして表示されますが、これらはキーワードではなく、String型のabcと同様の「リテラル定数」です。
3. コンパイラが .java ファイルをコンパイルするときに、「$」が上位の型と下位の型の間のコネクタにコンパイルされるため、名前を定義するときは $ の使用を避けるようにしてください。以下の例を参照してください:
package com.laixintao.Test; public class Outer$Inner { public static void main(String[] args) { Outer o = new Outer(); Outer.Inner i = o.new Inner(); i.innerPrint(); } } class Outer { class Inner { void innerPrint() { System.out.println("Inner Print!"); } } }
このコードをコンパイル (javac Test3.java) すると、コンパイラーは次のエラーを報告します: Test.java:12: Error: Duplicate class: com.laixintao.Test.Outer.Inner class Inner { ^
4. Unicode エスケープ文字は、解析プログラムの前の非常に早い段階で処理されます。例:
// char c1 = 'u00a'; // char c2 = 'u00d';
これらの 2 行のコードがプログラム内にあると、コンパイル エラーが発生します。これら 2 つの Unicode コードはそれぞれ「ライン フィード」と「キャリッジ リターン」を表すため、コンパイラがコンパイルすると、コードは次のようになります:
// char c1 = ' '; // char c2 = ' ';
5. Unicode コードは 16 ビット文字エンコーディングを使用し、Java では char 型を使用します。表現します。現在、Unicode は 100 万文字まで拡張されており、16 ビットの制限を超える文字は補助文字になります。すべての補助文字は文字定数で表すことはできません。
6. short、byte、char が演算に参加する場合、結果は上位の型と同じではなく、int 型になります。変数の型が byte、short、または byte で、コンパイル時定数が割り当てられており、その定数が変数の値の範囲を超えない場合、コンパイラは暗黙的な短縮変換を実行できます。この暗黙的な縮小変換は、変数の代入にのみ適用され、メソッド呼び出しステートメントには適用されないため、安全です。つまり、メソッド呼び出し時のパラメーターの受け渡しには適用されません。 (詳細については、Java のデフォルトの型変換に関するマイナーな問題を参照してください)
7. unsigned 型である char 型に注意してください。したがって、char と short、または char と byte の間の変換では、型変換を明示的に使用する必要があります。 byte から char への変換は、拡張および縮小変換です。つまり、最初に byte が拡張されて int に変換され、次に char に縮小されます。
8. 整数データ間の拡張変換では、オペランドがchar型(unsigned型)の場合はunsigned拡張を行い、拡張ビットは0となります。オペランドがbyte、short、int(signed型)の場合は、符号拡張を実行し、拡張ビットは変数の符号ビットです。
9. 整数データ間の短縮変換では、上位ビットのみが切り捨てられ、他の処理は行われません。
10, 0.1+0.2 は 0.3.System.out.println((double)0.1+(double)0.2); と等しくありません。 このステートメントの出力結果は 0.30000000000000004 です。コンピューターはデータの保存に 2 進数を使用し、10 進数を使用しても 1/3 などの分数を正確に表現できないのと同様に、多くの小数は 2 進数では正確に表現できません (実際、ほとんどの小数は近似値です)。ほとんどの浮動小数点型は、整数ほど正確ではなく、おおよその値をコンピュータに保存するだけです。別の例として、これは無限ループです: for(float f = 10.1f;f != 11;f+=0.1f){}
11。float 型は 7 ~ 8 個の有効数字を保持できますが、double 型は保持できます。有効桁数は 15 ~ 16 桁であるため、int 型または long 型の値が double または float よりも有効桁数が多い場合、値の最下位ビットの一部が失われ、結果として精度が失われます。最近接丸めモードを使用して、この整数値に最も近い浮動小数点値を抽出します。整数から浮動小数点への変換は拡張変換ですが、数値が非常に大きい場合や非常に小さい場合(絶対値が非常に大きい場合)、ある程度の精度の低下が発生します。
12. i+++j を計算するには? (この問題は C/C++ で説明されています) はあまり意味がありません。C/C++ は実装のハードウェア構造に依存しており、環境によって結果が異なるためです。ただし、Java では、この結果は固定されており、ハードウェア環境や実行されるプラットフォームの影響を受けません) 答え: 貪欲なルールによれば、接頭辞 ++ は後置 ++ よりも優れており、結果は (i++) + j となります。
13、i++ と ++i は実際には最初に +1 を加算してから値を割り当てます。 ++i、特に言うことはありません; i++、j=i++ を例にとると、基本的な実装は次のようになります。 したがって、式 i=15;i= i++; 結果は 15 になります。 (16 から 15 に戻すために 1 を加算した後に代入が行われるため)
浮動小数点型変数ストレージでは、14、+0、および -0 の符号ビットが異なります。 -0 と +0 が浮動小数点型関連の演算 (除算や剰余演算など) に関与すると、異なる結果が生成される可能性があります。
15. 浮動小数点の除算と剰余演算は、整数の除算と剰余演算とは異なります。除数が 0 の場合、浮動小数点演算は ArithmeticException を生成しません。
16. String クラスは、オブジェクトが作成されると破棄できません。文字シーケンスを変更するように見える String クラスのメソッドは、実際にはオブジェクト自体を変更するのではなく、新しく作成された String オブジェクトを返します。
17. String オブジェクトは不変であるため、スレッドセーフであり、自由に共有できます。
18 String クラス内では、文字シーケンスを維持するために文字配列 (char[]) が使用されます。 String の最大長は、文字配列の最大長であり、理論上は int 型の最大値 2147483647 となります。実際には、一般的に取得できる最大値は理論上の最大値よりも小さくなります。 。
19. main() メソッドは、パフォーマンス動作の点では他のメソッドと基本的に同じです。オーバーロード、他のメソッドによる呼び出し、継承、非表示が可能で、型パラメーターを使用して例外をスローすることもできます。プログラム内のリフレクションを通じて main メソッド (または他のメソッド) を呼び出すこともできます。
20. 2 つ以上のメソッドの名前は同じですが、パラメーター リストが異なる場合、これらのメソッドはオーバーロードを構成します。オーバーロードされたメソッドは、パラメーター リストに対応する型とパラメーターの数に基づいて区別できますが、パラメーターの名前、メソッドの戻り値の型、メソッドの例外リスト、および型パラメーターは使用できません。オーバーロードされたメソッドを区別するための条件。
21. どのメソッドを呼び出すか? 順序は次のとおりです:
最初の段階では、対応する仮パラメーターの型と仮パラメーターの型を検索することは考慮されません。パラメータ メソッドの数は実際のパラメータの数と同じです。
ステップ 1 で修飾されたメソッドがない場合は、2 番目のステージで自動ボックス化とアンボックス化が実行されます。
ステップ 2 で修飾されたメソッドがない場合、第 3 ステージでは、可変パラメータメソッドが考慮されます。
3つの段階で修飾されたメソッドが見つからない場合、コンパイルエラーが発生します。コンディショニングする方法が複数ある場合は、最も具体的な方法が選択されます。最も明確なメソッド定義は、メソッド A の対応する仮パラメータ リスト タイプをメソッド B の仮パラメータ リスト タイプに割り当てることができる場合、メソッド A はメソッド B よりも明確です。最も明確なメソッドを選択できない場合、コンパイル エラーが発生します。
22 オーバーライドと非表示の本質的な違いは、オーバーライドは動的にバインドされ、関連するクラスのメンバーは、ランタイム参照が指すオブジェクトの実際の型に基づいて呼び出されることです。 Hidden は静的にバインドされており、呼び出される関連メンバーはコンパイル時に参照される静的型に基づいて決定されます。つまり、サブクラスが親クラス メソッドをオーバーライドする場合、親クラス参照がサブクラス オブジェクトを指している場合、サブクラス メソッドは親クラス参照を通じて呼び出されます。サブクラスが親クラスのメソッド (メンバー変数) を隠している場合でも、親クラスのメソッド (メンバー変数) は親クラスへの参照を通じて呼び出されます。
23. コンストラクターは、Object クラスのコンストラクターが呼び出されるまで、再帰的に呼び出されます。
24 コンストラクターはオブジェクトを作成しません。コンストラクターは、new を使用してオブジェクトを作成するときにシステムによって呼び出され、クラスのインスタンス メンバーを初期化するために使用されます。順序的には、最初にオブジェクトが作成され、次にコンストラクターが呼び出されます。 (コンストラクターは新しいオブジェクトを生成しません)
25. デフォルトのコンストラクターは空ではありません。このコンストラクターは親クラスのパラメーターなしのコンストラクターを呼び出し、インスタンスのメンバー変数の初期化を実行する場合があります。したがって、デフォルトのコンストラクターは少なくとも親クラスのコンストラクターを呼び出し、インスタンス変数宣言の初期化やインスタンスの初期化ブロックなど、すべてコンストラクター内で実行される追加の作業を実行する場合があります。
26 == または != 演算子の 2 つのオペランドの一方が基本データ型で、もう一方がラッパー クラス参照型である場合、参照型をボックス化解除して基本データ型に変換し、2 つを比較します基本データ 型の値が等しいかどうか。
27. Java では、配列もクラスであり、配列内で宣言された参照変数は配列型のオブジェクトを指します。すべての配列は Object クラスを継承し、java.lang.Cloneable および java.io.Serializable インターフェイスを実装します。配列のメンバーには、可変長 (暗黙的に存在します) と Object クラスから継承されたメンバーが含まれます。 Cloneable と Serializable は、メンバーを明示的に宣言しない 2 つのマークされたインターフェイスです。
28. インターフェースは完全に抽象的なデザインであり、インスタンス化できません。新しいメソッドを使用して A によって作成された言い訳タイプを使用すると、実際にはインターフェイス タイプを実装する匿名クラスが作成されます。
29. 2 つのインターフェースが同じ変数を宣言した場合
30. 2 つのインターフェイスが同じ名前のメソッド m を宣言し、その 2 つのメソッドがオーバーロードを構成しない場合、インターフェイスが両方のインターフェイスを同時に継承できる場合、またはクラスが両方のインターフェイスを同時に継承できる場合、は、両方の m メソッド シグネチャのサブシグネチャであるメソッド シグネチャである必要があり、メソッドの戻り値の型が両方の m メソッドの戻り値の型の置換可能な型である必要があります。
上記は Java に関する一般的な誤解と詳細です。その他の関連コンテンツについては、PHP 中国語 Web サイト (m.sbmmt.com) にご注意ください。