ホームページ  >  記事  >  Java  >  Java の実行、コンパイル、操作の 2 つの概念の詳細な例

Java の実行、コンパイル、操作の 2 つの概念の詳細な例

Y2J
Y2Jオリジナル
2017-05-05 15:05:231272ブラウズ

この記事では、Java プログラムのコンパイル時間とランタイムについて、例を通して詳しく説明します。必要な方は参考にしてください。

Java のコンパイル時間とランタイムは非常に重要な概念ですが、今回は明確にしていません。概念を理解するために特別なブログを書いてください

基本概念

コンパイル時間とは、名前が示すように、コンパイルが行われるときのことです。ソース コードをマシンが認識できるコードに変換します (もちろん、これは一般的なものであり、実際には中間状態の言語に変換されるだけかもしれません。たとえば、Java には JVM によって認識されるバイトコードしかありません。さらに、理解を容易にするために、これをまとめてコンパイルと呼びます。

コンパイルとは、誤って間違ったキーワードを記述していないかどうかを確認することなどです。語彙分析、文法分析などのプロセスはありますか? 教師が生徒の作文にタイプミスや文章がないかをチェックするのと同じように、エラーが見つかった場合、コンパイラーはメモリが割り当てられていると言うことがあります。コンパイル中、これは間違いなく間違いです。

ランタイム

いわゆるランタイムは、コードが実行を開始し、メモリにロードされます(コードがディスクに保存され、ロードされていないときは無効です。メモリに実行されるときのみ有効になります)。ここで説明しているコンパイル時の型チェック (または

静的型チェック) は異なります。単にコードをスキャンするだけではありません。メモリ内でいくつかの操作を実行し、何らかの判断を下します (このようにして、コンパイル中に検出できない多くのエラーを実行時に検出できます。エラーが報告されたことがわかりました。書き込み時にこの論理エラーを回避するため)
たとえば

int arr[] = {1,2,3}; 
int result = arr[4]; 
System.out.println(result); 
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 4
上記のコードを見ると、それが間違ったコードであることがわかります。配列

は範囲外ですが、コンパイラはレポートしませんでした。エラーが発生しましたが、実行後に ArrayIndexOutOfBoundsException が発生しました。コンパイラは実際には非常に愚かであり、あなたの頭脳ほど賢くないことがわかります。したがって、コンパイラは少し愚かでも、実行中にエラーは発生しないと考えています。残念です

インタビューの質問

理解这几个概念可以更好地帮助你去了解一些基本的原理。下面是初学者晋级中级水平需要知道的一些问题。 
Q.下面的代码片段中,行A和行B所标识的代码有什么区别呢?

public class ConstantFolding {

 static final int number1 = 5;

 static final int number2 = 6;

 static int number3 = 5;

 static int number4= 6;

 public static void main(String[ ] args) {

 int product1 = number1 * number2; //line A

 int product2 = number3 * number4; //line B

 }

}
A. A 行のコードでは、product の値はコンパイル時に計算され、B 行は実行時に計算されます。 Java デコンパイラ (jd-gui など) を使用して ConstantFolding.class ファイルを逆コンパイルすると、次の結果から答えが得られます。
public class ConstantFolding
{
 static final int number1 = 5;
 static final int number2 = 6;
 static int number3 = 5;
 static int number4 = 6;

 public static void main(String[ ] args)
 {
 int product1 = 30;
 int product2 = number3 * number4;
 }
}

定数フォールディングは、Java コンパイラによって使用される最適化手法です。最終的な

変数

の値は変更されないため、最適化することができます。 Java デコンパイラと javap コマンドはどちらも、コンパイルされたコード (バイトコードなど) を表示するための強力なツールです。

メソッドのオーバーロード: これはコンパイル時に発生します。メソッドのオーバーロードは、コンパイラが引数の型に基づいて使用するメソッドを選択できるため、コンパイル時ポリモーフィズムとも呼ばれます。

public class {
 public static void evaluate(String param1); // method #1
 public static void evaluate(int param1); // method #2
}
コンパイラが次のステートメントをコンパイルしたい場合:

1evaluate(“My Test Argument pass to param1”) これは、渡されたパラメータ 文字列定数、#1 メソッドを呼び出すバイトコードを生成します

メソッド オーバーライド:

これは実行時に発生します。メソッドのオーバーロードは、コンパイル時にコンパイラがどのメソッドを呼び出すべきかを認識しておらず、認識できないため、実行時ポリモーフィズムと呼ばれます。 JVM はコードの実行中に決定を行います。 1evaluate(“My Test Argument passed to param1”);

它会根据传入的参数是字符串常量,生成调用#1方法的字节码

方法覆盖:这个是在运行时发生的。方法重载被称为运行时多态,因为在编译期编译器不知道并且没法知道该去调用哪个方法。JVM会在代码运行的时候做出决定。

public class A {
 public int compute(int input) { //method #3
 return 3 * input;
 } 
}

public class B extends A {
 @Override
 public int compute(int input) { //method #4
 return 4 * input;
 } 
}

子类B中的compute(..)方法重写了父类的compute(..)方法。如果编译器遇到下面的代码:

public int evaluate(A reference, int arg2) {
 int result = reference.compute(arg2);
}

编译器是没法知道传入的参数reference的类型是A还是B。因此,只能够在运行时,根据赋给输入变量“reference”的对象的类型(例如,A或者B的实例)来决定调用方法#3还是方法#4

泛型(又称类型检验):这个是发生在编译期的。编译器负责检查程序中类型的正确性,然后把使用了泛型的代码翻译或者重写成可以执行在当前JVM上的非泛型代码。这个技术被称为“类型擦除“。

换句话来说,编译器会擦除所有在尖括号里的类型信息,来保证和版本1.4.0或者更早版本的JRE的兼容性。

1List myList = new ArrayList(10);

编译后成为了:

1List myList = new ArrayList(10); rrreee
サブクラス B の compute(..) メソッドは、親クラスの compute(..) メソッドをオーバーライドします。コンパイラーが次のコードに遭遇した場合:

rrreee

コンパイラーには、渡されたパラメーター参照の型が A であるか B であるかを知る方法がありません。したがって、実行時に 入力変数

"reference" にのみ割り当てることができますメソッド #3 とメソッドのどちらを呼び出すかを決定するオブジェクト

のタイプ (A または B のインスタンスなど) #4

ジェネリック (型チェックとも呼ばれます): 🎜これはコンパイル時に発生します。コンパイラーは、プログラム内の型の正確性をチェックし、ジェネリックを使用するコードを現在の JVM で実行できる非ジェネリック コードに変換または書き換える責任を負います。この手法は「型消去」と呼ばれます。 🎜🎜言い換えると、コンパイラは、JRE バージョン 1.4.0 以前との互換性を確保するために、山かっこ内のすべての型情報を消去します。 🎜🎜1List myList = new ArrayList(10); 🎜🎜🎜 コンパイル後は次のようになります: 🎜🎜1List myList = new ArrayList(10); : 実行時例外またはコンパイル時例外を使用できます。 🎜🎜RuntimeException は未チェック例外とも呼ばれます。これは、この例外がコンパイラーによって検出される必要がないことを意味します。 🎜🎜RuntimeException は、実行時にスローされるすべての例外の親クラスです。例外をキャッチするだけでなく、メソッドは実行時に何かをスローする場合があります🎜<p>RuntimeException のサブクラスである場合、スローされた例外を宣言するために throw ステートメントを使用する必要はありません。 <br></p> <p>例: NullPointerException、ArrayIndexOutOfBoundsException など。<br></p> <p>チェック例外はコンパイル時にコンパイラによってチェックされ、検出例外は throws ステートメントまたは try{}cathch{} ステートメント ブロックを通じて処理されます。コンパイラーは、メソッドまたは<a href="http://www.php.cn/wiki/77.html" target="_blank">コンストラクター</a>の実行時にどの例外がスローされるかを分析します。 </p> <p>【関連おすすめ】</p> <p>1. <a href="http://www.php.cn/course/list/36.html" target="_self">無料のJavaビデオチュートリアル</a></p> <p>2. <a href="http://www.php.cn/course/346.html" target="_self">Alibaba Java開発マニュアル</a></p>3.

以上がJava の実行、コンパイル、操作の 2 つの概念の詳細な例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。