面接問題思考:tryコードブロックにreturn文が含まれている場合、コード実行順序

4601 ワード

Javaの面接問題でたまたま見た質問(try/finallyにreturnが含まれているときの実行順)が面白かったので、ちょっと研究してみましたが、私が油を注いで空を歩いた後、あなたに一定の助けをもたらすことを望んでいます.
原題
try{}にreturn文がありますが、このtryに続くfinally{}のコードは実行されますか?いつ実行されますか?returnの前ですか、それとも後ですか.
一见题目は简単ですか?java规范はすべて言って、finallyはtryコードブロックのreturnの前で実行して、あなたのこの文章は意味がなくて、见ません
待って!(私のそばにある五尺のナイフを取って)
不思議な栗
この栗を見て、実行順がどうなっているのか考えてみてください.
くりコード
    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
        }
    }

分析してみる
test()メソッド内でtryでtをreturnすると、mainメソッドではtest()関数の戻り値はt=0、すなわちコンソール出力0であるべきである
ただしfinallyが存在し、finallyではtが自己加算され、finallyはtryのreturn文の前に実行されるため、コンソール出力1が正しい
最終的に確定した答えはコンソール出力1です
しかし、実際にはそうではありません.プログラムを走った結果、次のような結果が得られました.
出力0で栗を走り出して自分の目で見てみましょう~
この結果を得たら爆発するかもしれない、何?JAva規範の言うことはすべて間違っていますか?!
急ぐ必要はありません.sunを洗う時間です.
せんじょうじかん
地面を洗う前にjavaの値伝達を理解する必要があります.この内容を知っていれば、次の小さなノードを省略することができます.
JAvaでの値転送
これは本文の内容が引用した知識点にすぎないので、余計なことを言って、勝手に一言言って、これで理解できればいいのですが、検索エンジンを借りて理解してほしいのではないでしょうか.
Javaのメソッド呼び出しでは、パラメータを渡す必要があることがよくありますが、渡すパラメータは前の変数をメソッドに直接渡しますか?
明らかに違います.メソッド伝達パラメータを呼び出すと、伝達されるのは元の変数のコピー(レプリカ)だけです.言い換えれば、変数の値をメソッドに伝達し、本当に変数を伝達していません.
栗を見てください.
    public static void main(String[] args) {
        int t = 0;
        test(t);
        System.out.println(t);
    }

    public static int test(int a) {
        a = 111;
    }

正確な出力は0であり,test()メソッド内で得られたaは,tのコピー(レプリカ)にすぎず,直接tではなくtest()内でaの値が変化し,tの値に影響を及ぼさないためである.
以上は基本データ型についてですが、オブジェクトについては?
パラメータがオブジェクトの場合、オブジェクトの参照のコピー(レプリカ)が渡されます.これは、メソッド内でオブジェクトを変更すると、オブジェクトが本当に変更される理由です.メソッドの体外参照とメソッド内の参照は、スタックメモリ内の同じオブジェクトを指し、オブジェクトの参照が伝達されるためです.
ここで値伝達が理解できない場合は、まずこの概念を理解してから下を見ることをお勧めします.
本当に分析を始めました
あなたが見やすいように、栗のコードをもう一つください.(私は本当に字を集めるためではありません)
    public static void main(String[] args) {
        int result = test();
        System.out.println(result);
    }

    public static int test() {
        int t = 0;
        try {
            return t;
        } finally {
            ++t;
        }
    }
  • コードがreturn t;に実行されると、直接tが返されるのではなく、tが保持される(finally文ブロックが実行されていないため!)

  • そしてこの保留は、値伝達の性質の保留であり、つまり保留されているのはtのコピー(複製体)であり、私はここでまず彼をttと呼びましょう(セットではありません!!)
  • は次にfinally文ブロックを実行し、finallyはtを自己加算し、tは確かに1になったが、これはtのレプリカttの値に影響しない!保留したtt値はまだ0です!
  • この時点でfinallyを実行し、正式に保持したttを返すと、関数全体の戻り結果は0
  • となる.
  • というtのコピー(レプリカ)が残っている場所はどこですか?私は半日調べて、頼りになるべき言い方があって、関数スタックの中に残っていますが、具体的に残っているエリアは何と呼ばれていますか.私も知りません.

  • 上図は直感的かもしれません.
    私に魂の絵師を呼んで、私は承諾することができます!
    では、もし、このtがオブジェクトだったら?前述した値伝達の問題によれば,tがオブジェクトでありfinallyでtを修正すると,最終的に返されるtに表示されるデータは,修正されたはずである.
    Person類を書いてチェックしてみましょう
    public class Test {
    
        public static void main(String[] args) {
            Person result = test();
            System.out.println(result.age);
        }
    
        public static Person test() {
            Person t = new Person();
            t.age = 0;
            try {
                return t;
            } finally {
                t.age++;
                
            }
        }
    
    }
    
    class Person {
        int age;
    }

    このコードは1を出力します.Personはクラスであり、tはオブジェクトの参照であり、オブジェクトインスタンスはスタックメモリに保存され、tのコピーttもオブジェクトの参照であり、tとttはスタックメモリのオブジェクトインスタンスを指しているので、誰を修正しても実際にはオブジェクトインスタンスは変更されます.
    私のこのでたらめを見て、あなたは実行プロセス全体を理解したはずですか?
    それでは引き続きご案内申し上げます
    もう一つの栗
    finallyにもreturnがあったら何が起こるの?
        public static void main(String[] args) {
            int result = test();
            System.out.println(result);
        }
    
        public static int test() {
            int t = 0;
            try {
                return t;
            } finally {
                ++t;
                return t;
            }
        }

    最終出力の結果は1
    つまり、tryにreturnがあり、finallyにもreturnがある場合、後者は前者を失効させます!
    理解する
    =>tryではtを返すためにコピーを残し、finallyではreturn文があり、このときに返すためのコピーを作成します.このとき2つのコピーがあります.いったい誰を返しますか.後者を取る!
    まとめ
    この面接問題は、簡単そうに見えますが、殺意を隠していますね.
    しかし、これだけ言ったらfinallyはreturnの後に実行されますか?
    いいえ、returnが本当に実行されていないのを見ていません.finallyを実行し始めましたか.さらにfinallyを実行してからreturnを実行するので、java仕様のfinallyがreturnの前に実行されていることがよく理解できます.
    しかし、このような場合、finallyはreturnより先に実行されます.もっと分かりやすいのではないでしょうか.
    つまり、returnが先に実行され、returnが実行されたときにfinallyがあることに気づき、そんなに早くreturnを実行することはできません.まずfinallyを実行し、finallyが実行されてから、returnが実行されます.
    全文下で、本当に私の3寸の腐らない舌で滔々とした出力を経て連綿と誘惑してあなたの新しい世界の扉を開けました
    締めくくり
    詳細は私のホームページやブログへようこそ.もし私の文章が確かに役に立つなら、文末の「♡」を注文して彼を「❤「ヒヨコとしては理解できないことが多いので、間違いがあったら直(bu)接(yao)指(ma)出(wo)で書くのは容易ではありません!