CodeGym/Java Blog/ランダム/Javaのメソッド
John Squirrels
レベル 41
San Francisco

Javaのメソッド

ランダム グループに公開済み
人のメンバー
またあったね!最後のレッスンでは、クラスとコンストラクターについて学び、独自のクラスとコンストラクターを作成する方法を学びました。今日は、クラスの重要な部分である Java メソッドについてさらに詳しく説明します。Java のメソッドは、プログラム内で特定の操作を実行できるようにする一連のコマンドです。言い換えれば、メソッドは関数です。あなたのクラスができること。他のプログラミング言語では、メソッドは「関数」と呼ばれることがよくありますが、Java では「メソッド」という言葉の方が一般的です。:) 覚えていると思いますが、前回のレッスンでは、猫がニャーと鳴いてジャンプできるように、 Catクラスの簡単なメソッドを作成しました。
public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();
    }
}
SayMeow()Jump() はこのクラスのメソッドです。これらのメソッドを実行すると、次のようなコンソール出力が得られます。
Meow!
Pounce!
私たちのメソッドは非常に単純です。単にテキストをコンソールに出力するだけです。しかし、Java では、メソッドにはオブジェクトのデータに対してアクションを実行するという重要なタスクがあります。オブジェクトのデータの変更、変換、表示などを行います。現在のメソッドは、 Catオブジェクトのデータを何も処理しません。よりわかりやすい例を見てみましょう。
public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
たとえば、ここにはTruckを表すクラスがあります。セミトラックには、長さ、幅、高さ、重量があります (後で必要になります)。getVolume()メソッドでは計算を実行し、オブジェクトのデータをその体積を表す数値に変換します (長さ、幅、高さを掛け合わせます)。この数値はメソッドの結果になります。メソッドの宣言はpublic int getVolumeとして記述されることに注意してください。つまり、このメソッドはintを返さなければなりません。メソッドの戻り値を計算しました。次に、その値をメソッドを呼び出したプログラムに返さなければなりません。Java でメソッドの結果を返すには、キーワード return を使用します。 戻り量。

Javaメソッドのパラメータ

メソッドを呼び出すときに、「引数」と呼ばれる値をメソッドに渡すことができます。メソッドの宣言には、メソッドが受け入れることができる変数の型と順序を示す変数のリストが含まれています。このリストは「メソッドパラメータ」と呼ばれます。TruckクラスのgetVolume()メソッドは現在パラメータを定義していないため、トラックの例を拡張してみましょう。BridgeOfficerという新しいクラスを作成します。これは橋で勤務している警察官で、通過するすべてのトラックをチェックして、荷物が許容重量を超えていないかどうかを確認しています。
public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
checkTruckメソッドは 1 つの引数、Truckオブジェクトを受け入れ、警察官トラックの橋上通行を許可するかどうかを決定します。メソッド内部のロジックは非常に単純です。トラックの重量が許容最大値を超えた場合、メソッドはfalseを返します。別の道路を探す必要があります:( 重みが最大値以下の場合は通過でき、メソッドはtrueを返します。。「戻る」または「メソッドが値を返す」という表現をまだ完全に理解していない場合は、プログラミングから離れて、実際の簡単な例を使用して考えてみましょう。:) あなたが病気になり、数日間仕事を休んで家にいるとしましょう。病気休暇には有給が支払われることになっているので、医師の診断書を持って会計部門に行きます。この状況をメソッドと比較すると、会計士にはpaySickLeave()があります。方法。医師の診断書を引数としてこのメ​​ソッドに渡します (医師の診断書がないとメソッドは機能せず、支払いも受けられません)。次に、メモを使用してメソッド内で必要な計算が行われ (会計士は会社があなたに支払うべき金額を計算するためにメモを使用します)、作業の結果 (金額) があなたに返されます。私たちのプログラムも同様の方法で動作します。メソッドを呼び出し、データを渡し、最終的に結果を受け取ります。BridgeOfficerプログラムのmain()メソッドは次のとおりです。
public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
積載量 10,000 個と 20,000 個のトラック 2 台を作成します。そして、警官が働いている橋の最大重量は15,000です。プログラムは、officer.checkTruck(first)メソッドを呼び出します。このメソッドはすべてを計算してtrueを返し、プログラムはそれをブール変数canFirstTruckGoに保存します。これで、(会計士からもらったお金でできるのと同じように)それを使ってやりたいことが何でもできるようになります。結局のところ、コードは
boolean canFirstTruckGo = officer.checkTruck(first);
要約すると
boolean canFirstTruckGo =  true;
ここは非常に重要な点です。returnステートメントはメソッドの戻り値を返すだけでなく、メソッドの実行も停止します。returnステートメントの後にあるコードは実行されません。
public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
メソッドはすでに結果を返して終了しているため、役員のコメントは表示されません。プログラムはメソッドが呼び出された場所に戻ります。これに注意する必要はありません。Java コンパイラは、 returnステートメントの後にコードを記述しようとすると、エラーを生成するほど賢明です。

アベンジャーズ:パラメータウォー

メソッドを呼び出す方法がいくつか必要になる場合があります。独自の人工知能を作成してみませんか? Amazon には Alexa があり、Apple には Siri があるのに、なぜ私たちがそれを持たないほうがいいのでしょうか? :) 映画『アイアンマン』では、トニー・スタークが独自の驚異的な人工知能、ジャービスを作成します。その素晴らしいキャラクターに敬意を表し、彼に敬意を表して AI に名前を付けましょう。:) 私たちが最初に行う必要があるのは、部屋に入ってくる人々に挨拶するようにジャービスに教えることです(そのような驚くべき知性が失礼であることが判明した場合は奇妙です)。
public class Jarvis {

    public void sayHi(String name) {
        System.out.println("Good evening, " + name + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
コンソール出力:
Good evening, Tony Stark. How are you?
とても良い!ジャービスはゲストを迎えることができるようになりました。もちろん、多くの場合、それは彼の主人であるトニー・スタークでしょう。でも、もし彼が一人で来なかったらどうしよう!SayHi()メソッドは引数を 1 つだけ受け入れます。したがって、部屋に入ってくる 1 人だけを歓迎し、もう 1 人は無視します。あまり礼儀正しくないと思いませんか?:/

Java メソッドのオーバーロード

この場合、同じ名前でパラメータが異なる 2 つのメソッドを記述するだけで問題を解決できます。
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }
}
これはメソッドのオーバーロードと呼ばれます。メソッドのオーバーロードにより、プログラムがより柔軟になり、さまざまな作業方法に対応できるようになります。どのように機能するかを確認してみましょう。
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
コンソール出力:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
素晴らしいですね、両方のバージョンが機能しました。:) しかし、問題は解決しませんでした。ゲストが3人だったらどうしますか?もちろん、sayHi()メソッドを再度オーバーロードして、3 つのゲスト名を受け入れるようにすることもできます。しかし、4 つや 5 つある可能性もあり、無限に至るまであります。SayHi()メソッドを何百万回もオーバーロードせずに、ジャービスに任意の数の名前を処理できるように教える、もっと良い方法はないでしょうか? :/ もちろんあります! もしそれがなかったら、Java は世界で最も人気のあるプログラミング言語になると思いますか? ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
( String... names ) がパラメータとして使用される場合、文字列のコレクションがメソッドに渡されることを示します。事前にその数を指定する必要がないため、この方法はより柔軟になりました。
public class Jarvis {

    public void sayHi(String...names) {
        for (String name: names) {
            System.out.println("Good evening, " + name + ". How are you?");
        }
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
コンソール出力:
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
ここには見慣れないコードも含まれていますが、心配する必要はありません。本質的にはシンプルです。このメソッドは、各ゲストの名前を順番に受け取り、各ゲストに挨拶します。さらに、渡された文字列の数に関係なく機能します。2 人、10 人、さらには 1,000 人でも、この方法はゲストの数に関係なく適切に機能します。すべての可能性を考慮してメソッドをオーバーロードするよりもはるかに便利だと思いませんか? :) ここでもう 1 つの重要な点があります。引数の順序が重要です。私たちのメソッドが文字列と数値を取るとしましょう:
public class Person {

    public static void sayYourAge(String greeting, int age) {
        System.out.println(greeting + " " + age);
    }

    public static void main(String[] args) {
        sayYourAge("My age is ", 33);
        sayYourAge(33, "My age is "); // Error!
    }
}
PersonクラスのsayYourAgeメソッドが文字列と数値を入力として受け取る 場合、プログラムはそれらをその特定の順序で渡す必要があります。異なる順序で渡すと、コンパイラはエラーを生成し、その人は自分の年齢を言うことができなくなります。ちなみに、前回のレッスンで説明したコンストラクターもメソッドです。また、それらをオーバーロードすることもできます (つまり、異なるパラメーターのセットを持つ複数のコンストラクターを作成する) が、渡される引数の順序も基本的に重要です。それらは本物のメソッドなのです!:)

もう一度パラメータについて

はい、申し訳ありませんが、まだ終わっていません。:) これから勉強するトピックは非常に重要です。今後のすべての面接でこのことについて質問される可能性が 90% あります。メソッドに引数を渡すことについて話しましょう。簡単な例を考えてみましょう。
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What year is it?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
タイムマシンには2つの方法があります。どちらも現在の年を表す数値を入力として受け取り、(過去に行きたいか未来に行きたいかに応じて)その値を増減します。しかし、コンソール出力からわかるように、この方法は機能しません。コンソール出力:
What year is it?
2018
How about now?
2018
currentyear変数をgoToPast()メソッドに渡しましたが、その値は変わりませんでした。私たちは 2018 年に滞在しましたが、ここに留まりました。しかし、なぜ?:/ Java のプリミティブは値によってメソッドに渡されるためです。どういう意味ですか?goToPast()メソッドを呼び出してint変数currentyear (=2018)を渡すと、メソッドはcurrentyear変数自体を取得するのではなく、そのコピーを取得します。もちろん、このコピーの値も 2018 ですが、コピーに変更を加えても、元のcurrentyear変数にはまったく影響しません。コードをより明示的にして、current Year で何が起こるかを見てみましょう。
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started running!");
        System.out.println("currentYear inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("currentYear inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
コンソール出力:
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
これは、 goToPast()メソッドに渡される変数がcurrentyearのコピーにすぎないことを明確に示しています。また、コピーを変更しても「元の」値には影響しません。「参照渡し」はまったく逆の意味です。猫で練習してみよう!つまり、猫の例を使用して、参照による受け渡しがどのようなものかを見てみましょう。:)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
タイムマシンの助けを借りて、世界初のタイムトラベル猫スマッジを過去と未来に 送りましょう! Catオブジェクトで動作するようにTimeMachineクラスを変更しましょう。
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
現在、メソッドは渡された数値を変更するだけではありません。むしろ、特定のCat年齢フィールドを変更します。元の数値が変わらないため、プリミティブではこれが機能しなかったことを思い出してください。何が起こるか見てみましょう!
public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat smudge = new Cat(5);

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
コンソール出力:
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
おお!さて、この方法は何か違うことをしました。私たちの猫は大幅に老化しましたが、その後再び若くなりました。:) その理由を考えてみましょう。プリミティブの例とは異なり、オブジェクトがメソッドに渡されるとき、それらは参照によって渡されます。元の汚れオブジェクトへの参照が、changeAge()メソッドに渡されました。したがって、メソッド内でsmudge.ageを変更すると、オブジェクトが保存されているのと同じメモリ領域を参照することになります。これは、最初に作成したのと同じスマッジへの参照です。これを「参照渡し」といいます。ただし、参照を伴うものすべてがそれほど簡単であるわけではありません。:) 例を変更してみましょう:
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

        timeMachine.goToFuture(smudge);
        System.out.println ("Smudge went to the future! Has his age changed?");
        System.out.println(smudge.age);

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
コンソール出力:
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
またうまくいきません!О_О 何が起こったのか見てみましょう。:) これはgoToPast / goToFutureメソッドと参照の仕組みにすべて関係しています。さあ、注目してください!これは、参照とメソッドがどのように機能するかを理解するために最も重要なことです。実際、goToFuture(Cat cat)メソッドを呼び出すと、渡されるのは参照そのものではなく、 cat オブジェクトへの参照のコピーです。したがって、オブジェクトをメソッドに渡すとき、オブジェクトへの参照が 2 つ存在します。これは何が起こっているのかを理解するために非常に重要です。まさにこれが、最後の例で猫の年齢が変わらなかった理由です。前の例では、年齢を変更するときに、単にgoToFuture()に渡された参照を取得しました。メソッドを作成し、それを使用してメモリ内のオブジェクトを検索し、その年齢を変更しました ( cat.age += 10 )。ただし、goToFuture()メソッド内で新しいオブジェクト ( cat = new Cat(cat.age) ) を作成しており、このオブジェクトにはメソッドに渡されたのと同じ参照コピーが割り当てられます。結果として:
  • 最初の参照 ( Cat smudge = new Cat (5) ) は、元の猫 (年齢 5 歳) を指します。
  • その後、cat 変数をgoToPast()メソッドに渡し、それに新しいオブジェクトを割り当てると、参照がコピーされました。
そして、これにより最終的な結果が得られました。2 つの参照が 2 つの異なるオブジェクトを指しているということです。ただし、そのうちの 1 つ (メソッド内で作成されたもの) の年齢を変更しただけです。
cat.age += 10;
そしてもちろん、main()メソッドでは、猫の年齢smudge.age が変わっていないことがコンソールで確認できます。結局のところ、smudge は、年齢 5 の古い元のオブジェクトをまだ指している参照変数であり、そのオブジェクトに対しては何もしていません。すべての年齢変更は新しいオブジェクトに対して実行されました。 したがって、オブジェクトは参照によってメソッドに渡されることがわかります。オブジェクトのコピーが自動的に作成されることはありません。cat オブジェクトをメソッドに渡してその年齢を変更すると、その年齢も変更されます。ただし、参照変数は、値を割り当てたりメソッドを呼び出したりするときにコピーされます。プリミティブの受け渡しについて述べたことをここで繰り返しましょう。「changeInt()メソッドを呼び出してintを渡すとき」変数x (=15)の場合、メソッドは変数x自体を取得するのではなく、そのコピーを取得します。したがって、コピーに加えられた変更は元のxには影響しません。Java で引数がどのように渡されるかについては、依然として (経験豊富な開発者の間でも) 何度も議論することになります。しかし、これで、それがどのように機能するかが正確にわかりました。がんばり続ける!:) 学んだことをさらに強化するには、Java コースのビデオ レッスンを視聴することをお勧めします。
コメント
  • 人気
  • 新規
  • 古い
コメントを残すには、サインインしている必要があります
このページにはまだコメントがありません