ホームページ >Java >&#&チュートリアル >Java JVM メソッドディスパッチモデルの使用方法

Java JVM メソッドディスパッチモデルの使用方法

WBOY
WBOY転載
2023-04-21 10:49:071373ブラウズ

1. ナレッジ リザーブ

1.1 ディスパッチ

  • 定義: 実行するメソッドを決定するプロセス

a. 質問 読者の中には、メソッドの実行はコード設定の実行オブジェクトに依存しないのではないかと尋ねる人もいるでしょう。なぜ選ぶのでしょうか? b. 回答

  • オブジェクトが複数のメソッドに対応する場合は、選択する必要があります

  • 読者は次のことを行う必要があります。誰もが Java の機能、つまりポリモーフィズム、つまり書き換えとオーバーロードを考えました。以下で詳しく説明します。

  • カテゴリ: 静的ディスパッチと動的ディスパッチ。以下で詳しく説明します。

#1.2 変数の静的型と動的型

まず次のコードを見てください

public class Test { 
    static abstract class Human { 
    } 
    static class Man extends Human { 
    } 
    static class Woman extends Human { 
    } 
// 执行代码
public static void main(String[] args) { 
  Human man = new Man(); 
  // 变量man的静态类型 = 引用类型 = Human:不会被改变、在编译器可知
  // 变量man的动态类型 = 实例对象类型 = Man:会变化、在运行期才可知
    } 
}

つまり:

  • 変数の静的型 = 参照型: 変更されません、コンパイル時にわかります

  • 変数の動的型 = インスタンス オブジェクトの型: 変更されます、わかります実行時

以下では、

Javaにおけるディスパッチの種類、静的ディスパッチと動的ディスパッチ

2について詳しく説明します。

    ##変数の静的型に基づいてメソッドディスパッチの動作を定義します
    つまり、どのメソッドをディスパッチするかを決定します。変数の静的型に基づいて実行
  • # はコンパイル中に発生するため、
  • Java

    仮想マシンは実行されません

##アプリケーション シナリオ メソッドのオーバーロード (
    OverLoad
  • )

    例の説明
  • public class Test { 
    // 类定义
        static abstract class Human { 
        } 
    // 继承自抽象类Human
        static class Man extends Human { 
        } 
        static class Woman extends Human { 
        } 
    // 可供重载的方法
        public void sayHello(Human guy) { 
            System.out.println("hello,guy!"); 
        } 
        public void sayHello(Man guy) { 
            System.out.println("hello gentleman!"); 
        } 
        public void sayHello(Woman guy) { 
            System.out.println("hello lady!"); 
        } 
    // 测试代码
        public static void main(String[] args) { 
            Human man = new Man(); 
            Human woman = new Woman(); 
            Test test = new Test(); 
            test.sayHello(man); 
            test.sayHello(woman); 
        } 
    }
    // 运行结果
    hello,guy! 
    hello,guy!

    によると、上記の説明で、操作結果の理由は誰でも理解できるはずです。

メソッドのオーバーロード (
    OverLoad
  • ) = 静的ディスパッチ = に基づいて、どのメソッドを実行 (オーバーロード) するかを決定します。変数の静的型

    So 上記のメソッドが実行されると、オーバーロード
  • sayHello()
  • は静的型 (

    Human#) に基づいて決定されます。 ##) の変数 (man, women) パラメーター Human guy を持つメソッド、つまり sayHello(Human guy)

  • a. 変数に特に注意してください静的型が変更される場合

forced を使用して変数の静的型を変更できます。型変換

Human man = new Man(); 
test.sayHello((Man)man); 
// 强制类型转换
// 此时man的静态类型从 Human 变为 Man
// 所以会调用sayHello()中参数为Man guy的方法,即sayHello(Man guy)

b. 静的ディスパッチの優先度マッチング問題

問題の説明:

  • バックグラウンドを静的にディスパッチする必要があります
  • 問題はプログラムに表示されません静的タイプを指定してください

  • ソリューション プログラム静的タイプの優先順位に基づいて、メソッド割り当てに優先される静的タイプを選択します。

  • 例の説明

    public class Overload {  
        private static void sayHello(char arg){  
            System.out.println("hello char");  
        }  
        private static void sayHello(Object arg){  
            System.out.println("hello Object");  
        }  
        private static void sayHello(int arg){  
            System.out.println("hello int");  
        }  
        private static void sayHello(long arg){  
            System.out.println("hello long");  
        }  
    // 测试代码
        public static void main(String[] args) {  
            sayHello('a');  
        }  
    }  
    // 运行结果
    hello char

  • ‘a’

char

型データ (つまり、静的型) であるため、

char) であるため、パラメータ型 char のオーバーロードされたメソッドが選択されます。 sayHello(char arg) メソッドをコメントアウトすると、‘a’

は文字列だけを表すことができないため、

hello int
が出力されます。だけでなく、数字の 97 を表すこともできます。したがって、最も適切な

sayHello(char arg) オーバーロード方法がない場合は、2 番目に適切な (2 番目の優先順位) メソッドが選択されます。オーバーロード、つまり <strong></strong>sayHello(int arg)概要: オーバーロードに最適なメソッドがない場合は、2 番目の優先順位が選択されます。上位のメソッドがオーバーロードされているなど。 <strong></strong>優先順位は次のとおりです:

##char>int>long>float>double>Character>Serializable>Object>...

where

...
は可変長パラメータであり、配列要素として扱われます。可変長パラメータのオーバーロード優先度は最も低くなります。

char

byte または

short

に変換するプロセスは安全ではないため、パラメーター タイプは byte# として選択されません。 ## または short メソッドはオーバーロードされているため、優先リストには含まれていません。 特別な注意上記の説明は、主に 基本データ型の優先度一致問題についてです。

  • # #参照型の場合、優先順位の一致は

    継承関係に基づいて実行されます

  • これはコンパイル時の型 (つまり、静的型)

    3. 動的ディスパッチ

変数の動的型に基づいてメソッド ディスパッチの動作を定義します

つまり、変数の動的型に基づいて実行するメソッドを決定します
  • #アプリケーション シナリオ メソッド オーバーライド (

    Override
  • )

#インスタンスの説明
  • // 定义类
        class Human { 
            public void sayHello(){ 
                System.out.println("Human say hello"); 
            } 
        } 
    // 继承自 抽象类Human 并 重写sayHello()
        class Man extends Human { 
            @Override 
            protected void sayHello() { 
                System.out.println("man say hello"); 
            } 
        } 
        class Woman extends Human { 
            @Override 
            protected void sayHello() { 
                System.out.println("woman say hello"); 
            } 
        } 
    // 测试代码
        public static void main(String[] args) { 
            // 情况1
            Human man = new man(); 
            man.sayHello(); 
            // 情况2
            man = new Woman(); 
            man.sayHello(); 
        } 
    }
    // 运行结果
    man say hello
    woman say hello
    // 原因解析
    // 1. 方法重写(Override) = 动态分派 = 根据 变量的动态类型 确定执行(重写)哪个方法
    // 2. 对于情况1:根据变量(Man)的动态类型(man)确定调用man中的重写方法sayHello()
    // 3. 对于情况2:根据变量(Man)的动态类型(woman)确定调用woman中的重写方法sayHello()
    特別な注意

    コードについて:
  • Human man = new Man(); 
    man = new Woman(); 
    man.sayHello(); 
    // man称为执行sayHello()方法的所有者,即接受者。
  • invokevirtual
命令実行の最初のステップ = 受信者の実際のタイプを決定します

    invokevirtual
  • 命令実行の 2 番目のステップ =

    クラス メソッドのシンボル参照を解決します定数プール内で別の直接参照への#

##2 番目のステップは、メソッド オーバーライド (

Override)

4 の本質です。2 つのステップの違い

##

以上がJava JVM メソッドディスパッチモデルの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。