JavaRush /Java Blog /Random-JA /メソッドのシグネチャ

メソッドのシグネチャ

Random-JA グループに公開済み
こんにちは!フィールドとメソッドを使用して独自のクラスを作成する方法はすでに習得しました。今日はその方法について詳しくお話します。もちろん私たちも講義の中で何度かやりましたが、主に一般的なことを話しました。今日は文字通りメソッドを「部分的に」分析します - メソッドが何で構成されているか、メソッドを作成するためのオプションが存在するか、そしてこれらすべてをどのように管理できるかを調べます:) さあ、行きましょう!メソッド署名 - 1

メソッドのシグネチャ

メソッドを記述するすべてのコードは、メソッド宣言と呼ばれます。メソッド シグネチャには、メソッド名とパラメータ タイプが特定の順序で含まれます。広告の一般的な外観は次のように説明できます。
модификатор доступа, тип возвращаемого значения, Name метода(список параметров) {
    // тело метода
}
クラスのいくつかのメソッドの宣言の例を見てみましょうDog
public class Dog {

   String name;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {
       Dog max = new Dog("Max");
       max.woof();

   }

   public void woof() {
       System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
   }

   public void run(int meters) {
       System.out.println("Собака по имени " + name + " пробежала " + meters + " метров!");
   }

   public String getName() {
       return name;
   }
}

1. アクセス修飾子

アクセス修飾子は常に最初にリストされます。 すべてのクラス メソッドは、Dog修飾子によって指定されますpublic。つまり、他のクラスから呼び出すことができます。
public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Бутч");
       butch.run(100);
   }

}
Dogご覧のとおり、 クラス メソッドにはクラス内で簡単にアクセスできますMain。これは修飾子 のおかげで可能になりますpublic。Java には他にも修飾子があり、それらすべてが別のクラス内でメソッドを使用できるわけではありません。それらについては、他の講義でお話します。重要なことは、修飾子が何を担当するのか、つまり他のクラスでのメソッドの可用性/アクセス不可能性を覚えておくことです:)

2. 静的キーワード

Dogそのうちの1 つの方法をmain()キーワード で示しますstatic。存在する場合は、アクセス修飾子の後に指定する必要があります。以前の講義で静的クラス変数について話したのを覚えていますか? メソッドに適用される場合、この単語はほぼ同じ意味を持ちます。メソッドが として指定されている場合static、これは、特定のクラス オブジェクトを参照せずにメソッドを使用できることを意味します。実際、main()クラス内で静的メソッドを実行する場合、Dogインスタンスを作成する必要はなくDog、インスタンスなしでも実行されます。このメソッドが静的でない場合、それを使用するには、まずオブジェクトを作成する必要があります。

3. 戻り値。

メソッドが何かを返す必要がある場合は、戻り値の型を示します。これは getter の例で見ることができますgetName()
public String getName() {
   return name;
}
型のオブジェクトを返しますString。メソッドが何も返さない場合は、void次のメソッドのように、 type の代わりにキーワードが指定されますwoof()
public void woof() {
   System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
}

同じ名前のメソッド

プログラムがメソッドの動作方法について複数のオプションを必要とする場合があります。独自の人工知能を作成してみませんか? Amazon には Alexa があり、Yandex には Alice があるのに、なぜ私たちは劣っているのでしょうか? :) アイアンマンの映画で、トニー スタークは独自の優れた人工知能を作成しました - JARVIS この素晴らしいキャラクターに敬意を表し、彼に敬意を表して AI に名前を付けましょう :)私たちが最初にジャービスに教えなければならないことは、部屋に入ってきた人に挨拶することです(そのような優れた知性が失礼であることが判明した場合は奇妙です)。
public class Jarvis {

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
コンソール出力:

Добрый вечер, Тони Старк, How ваши дела?
素晴らしい!ジャービスは入ってきた人に挨拶する方法を知っています。もちろん、ほとんどの場合、それは彼の飼い主であるトニー・スタークでしょう。でも、彼は一人では来られないかもしれません!そして、私たちのメソッドはsayHi()入力として引数を 1 つだけ受け取ります。そして、それに応じて、彼は来た人の一人だけを挨拶することができ、もう一人は無視するでしょう。あまり丁寧ではありませんが、同意しますか?:/ この場合、問題を解決するには、クラス内に同じ名前で異なるパラメータを持つ 2 つのメソッドを記述するだけです。
public class Jarvis {

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

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

}
これはメソッドのオーバーロードと呼ばれます。オーバーロードにより、プログラムがより柔軟になり、さまざまな作業オプションに対応できるようになります。どのように動作するかを確認してみましょう:
public class Jarvis {

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

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
コンソール出力:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Тони Старк, Капитан Америка, How ваши дела?
素晴らしいですね、どちらのオプションもうまくいきました :) しかし、問題は解決しませんでした。ゲストが3人だったらどうしますか?もちろん、メソッドを再度オーバーロードしてsayHi()3 人のゲストの名前を受け入れることができます。ただし、その数は 4 つまたは 5 つになる可能性があり、それが無限に続きます。100 万ものメソッドをオーバーロードせずに、任意の数の名前を扱えるように Jarvis に教える別の方法はありますかsayHi()? :/ もちろん持っています! そうでなければ、Java は世界で最も人気のあるプログラミング言語になるでしょうか? ;)
public class Jarvis {

   public void sayHi(String...names) {

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
パラメーターとして渡されるレコード ( String...names) を使用すると、特定の数の文字列がメソッドに渡されることを示すことができます。いくつあるべきかを事前に指定しないため、メソッドの操作がより柔軟になります。
public class Jarvis {

   public void sayHi(String...names) {

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
   }
}
コンソール出力:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Капитан Америка, How ваши дела? 
Добрый вечер, Черная Вдова, How ваши дела? 
Добрый вечер, Халк, How ваши дела?
メソッド内で、すべての引数をループし、名前付きの既製のフレーズをコンソールに出力します。ここでは、簡略化されたループを使用しますfor-each(すでに使用したことがあるでしょう)。String...names実際、書き込みとは、渡されたすべてのパラメーターがコンパイラーによって配列に入れられることを意味するため、これは素晴らしいことです。したがって、 names変数をループするなど、配列と同様に変数を操作できます。しかも転送回線数に関係なく使えます!2 人、10 人、さらには 1,000 人のゲストでも、この方法はどのような人数でも確実に機能します。考えられるすべてのオプションに対してオーバーロードを行うよりもはるかに便利ですよね? :) メソッドのオーバーロードの別の例を見てみましょう。Jarvis にメソッドを追加しましょうprintInfoFromDatabase()。その人に関する情報をデータベースからコンソールに出力します。データベースがその人がスーパーヒーローまたはスーパーヴィランであることを示している場合、この情報も画面に表示されます。
public class Jarvis {

   public  void printInfoFromDatabase (String bio) {

       System.out.println(bio);
   }

   public void printInfoFromDatabase(String bio, boolean isEvil, String nickname) {

       System.out.println(bio);
       if (!isEvil) {
           System.out.println("Также известен How супергерой " + nickname);
       } else {
           System.out.println("Также известен How суперзлодей " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Макс Эйзенхарт. Рост 188см, вес 86 кг.", true, "Магнето");
   }
}
結論:

Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington
Макс Эйзенхарт. Рост 188см, вес 86 кг 
Также известен How суперзлодей Магнето
これは、渡すデータに応じてメソッドがどのように機能するかです。 もう 1 つの重要な点:引数の順序は重要です。私たちのメソッドが文字列と数値を入力として受け取るとします。
public class Man {

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

   public static void main(String[] args) {

       sayYourAge("My age - ", 33);
       sayYourAge(33, "My age - "); //error!
   }
}
sayYourAge()クラスメソッドが文字列と数値を入力として受け取る 場合Man、プログラム内ではこの順序で渡す必要があります。異なる順序で渡すと、コンパイラはエラーをスローし、その人は自分の年齢を判断できなくなります。ちなみに、前回の講義で取り上げたコンストラクターもメソッドです。また、オーバーロードすることもできます (さまざまな引数のセットを使用して複数のコンストラクターを作成する) ため、引数を渡す順序も基本的に重要です。実際のメソッド! :)

同様のパラメータを持つメソッドを呼び出す方法

ご存知のとおり、Java には null という言葉があります。これを扱う場合、null はオブジェクトでもデータ型でもないことを理解することが非常に重要です。Man クラスと、introduce()人の名前と年齢を宣言するメソッドがあると想像してください。この場合、年齢はテキスト形式で伝えることもできますし、数値で表現することもできます。
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man sasha = new Man();
       sasha.introduce("Sasha", "двадцать один");

       Man masha = new Man();
       masha.introduce("Мария", 32);
   }
}
私たちはすでにオーバーロードに精通しているため、このメソッドがどちらの場合も期待どおりに機能することがわかります。

Меня зовут Саша, мой возраст - двадцать один 
Меня зовут Мария, мой возраст - 32 
しかし、2 番目のパラメータとして文字列や数値ではなく null を渡した場合はどうなるでしょうか?
public static void main(String[] args) {

   Man victor = new Man();
   victor.introduce("Виктор", null);//Ambiguous method call!
}
コンパイルエラーが発生します! 「あいまいなメソッド呼び出し」エラーは「あいまいなメソッド呼び出し」と訳されます。なぜそれが生じるのか、そしてその「曖昧さ」とは何でしょうか? 実は簡単なんです。問題は、このメソッドには 2 つのバリアント (withStringと with をInteger2 番目の引数として使用する) があるということです。ただしString、 と は両方ともIntegernull にすることができます。どちらの型でも (参照型であるため)、null がデフォルト値です。そのため、この状況ではコンパイラはどのバージョンのメソッドを呼び出す必要があるかを判断できません。この問題を解決するのは非常に簡単です。重要なのは、null を特定の参照型に明示的に変換できることです。したがって、メソッドを呼び出すときに、2 番目の引数に必要なデータ型を括弧内に指定できます。コンパイラはあなたの「ヒント」を理解し、必要なメソッドを呼び出します。
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Метод со строкой и числом!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", (String) null);
   }
}
結論:

Метод с двумя строками! 
Меня зовут Виктор, мой возраст - null
ただし、数値パラメーターがint参照型のオブジェクトではなく、プリミティブである場合Integer、そのようなエラーは発生しません。
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Метод со строкой и числом!!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", null);
   }
}
理由はわかりましたか? 推測できたなら、よくやった :) プリミティブを null に等しくすることはできないからです。現在、コンパイラにはメソッドを呼び出すためのオプションが 1 つだけありintroduce()、2 行で実行されます。メソッドが呼び出されるたびに処理されるのは、このバージョンのメソッドです。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION