JavaRush /Java Blog /Random-KO /메소드 서명

메소드 서명

Random-KO 그룹에 게시되었습니다
안녕하세요! 필드와 메서드를 사용하여 자신만의 클래스를 만드는 방법을 이미 마스터했습니다. 오늘은 그 방법에 대해 자세히 이야기하겠습니다. 물론 우리는 강의에서 이것을 두 번 이상 해왔지만 주로 일반적인 사항에 대해 이야기했습니다. 오늘 우리는 "부분적으로" 방법을 문자 그대로 분석할 것입니다. 그것이 무엇으로 구성되어 있는지, 어떤 옵션을 생성하는지, 그리고 이 모든 것을 어떻게 관리할 수 있는지 알아볼 것입니다. :) 가자!메소드 서명 - 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. 접근 수정자

액세스 수정자는 항상 먼저 나열됩니다. 모든 클래스 메소드는 Dogmodifier로 지정됩니다 public. 즉, 다른 클래스에서 호출할 수 있습니다.
public class Main {

   public static void main(String[] args) {

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

}
Dog보시다시피 클래스 메소드는 클래스에서 쉽게 액세스할 수 있습니다 Main. 이는 modifier 덕분에 가능합니다 public. Java에는 다른 수정자가 있지만 이들 중 일부는 다른 클래스 내에서 메소드를 사용할 수 있도록 허용하지 않습니다. 이에 대해서는 다른 강의에서 다루겠습니다. 가장 중요한 것은 수정자가 담당하는 것이 무엇인지 기억하는 것입니다: 다른 클래스에서 메소드의 가용성/접근 불가능성 :)

2. 정적 키워드

방법 중 하나는 Dog키워드 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가 있는데 왜 우리는 더 나쁠까요? :) Iron Man에 관한 영화에서 Tony Stark는 자신의 뛰어난 인공 지능을 만들었습니다. JARVIS 멋진 캐릭터에 경의를 표하고 그를 기리기 위해 AI의 이름을 지정합시다 :) 먼저 Jarvis에게 가르쳐야 할 것은 방에 들어오는 사람들에게 인사하는 것입니다(그렇게 뛰어난 지성이 무례한 것으로 판명된다면 이상할 것입니다).
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 ваши дела?
엄청난! 자비스는 들어오는 사람에게 인사하는 방법을 알고 있습니다. 물론 대부분의 경우 소유자는 Tony Stark입니다. 하지만 그는 혼자 오지 않을 수도 있습니다! 그리고 우리의 방법은 sayHi()단 하나의 인수만 입력으로 사용합니다. 따라서 그는 오는 사람들 중 한 사람에게만 인사할 수 있고 다른 사람은 무시할 것입니다. 그다지 정중하지는 않습니다. 동의하십니까?:/ 이 경우 문제를 해결하려면 클래스에 이름은 같지만 매개변수가 다른 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 ваши дела?
좋습니다. 두 가지 옵션 모두 효과가 있었습니다. :) 그러나 문제는 해결되지 않았습니다! 손님이 세 명이라면 어떨까요? 물론 sayHi()세 명의 손님 이름을 받아들이도록 메서드를 다시 오버로드할 수 있습니다. 하지만 그 중 4~5개가 있을 수 있으며, 무한정 계속됩니다. 백만 개의 메서드 오버로드 없이 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명, 심지어 1000명 - 이 방법은 손님 수에 관계없이 안정적으로 작동합니다. 가능한 모든 옵션에 대해 오버로드를 수행하는 것보다 훨씬 편리하다는 점에 동의하지 않나요? :) 메소드 오버로딩의 또 다른 예를 들어보겠습니다. 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 суперзлодей Магнето
이것이 우리가 전달하는 데이터에 따라 우리의 방법이 작동하는 방식입니다. 또 다른 중요한 점:인수의 순서가 중요합니다! 우리의 메소드가 문자열과 숫자를 입력으로 사용한다고 가정해 보겠습니다.
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 
그런데 두 번째 매개변수로 문자열이나 숫자가 아닌 null을 전달하면 어떻게 될까요?
public static void main(String[] args) {

   Man victor = new Man();
   victor.introduce("Виктор", null);//Ambiguous method call!
}
컴파일 오류가 발생합니다! "모호한 메서드 호출" 오류는 "모호한 메서드 호출"로 번역됩니다. 왜 이런 일이 발생할 수 있으며 "모호함"은 무엇입니까? 실제로는 간단합니다. 문제는 메소드에 두 가지 변형이 있다는 것입니다. 두 번째 인수로 with String와 with가 있습니다. Integer그러나 String, 및 둘 다 Integernull일 수 있습니다! 두 유형 모두(참조 유형이므로) 기본값은 null입니다. 이것이 바로 이 상황에서 컴파일러가 호출해야 하는 메서드 버전을 파악할 수 없는 이유입니다. 이 문제를 해결하는 것은 아주 간단합니다. 요점은 null이 특정 참조 유형으로 명시적으로 변환될 수 있다는 것입니다. 따라서 메소드를 호출할 때 두 번째 인수에 필요한 데이터 유형을 괄호 안에 표시할 수 있습니다! 컴파일러는 "힌트"를 이해하고 필요한 메서드를 호출합니다.
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과 같을 수 없기 때문입니다. 이제 컴파일러에는 introduce()두 줄의 메서드 호출 옵션이 하나만 있습니다. 메소드가 호출될 때마다 처리되는 것은 이 버전의 메소드입니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION