Java соответствие имени функции, но разные аргументы - PullRequest
0 голосов
/ 10 января 2020

Я на самом деле из python фона, и я изучал "взломать интервью по кодированию" в java. На странице 51 я наткнулся на

void permutation(String str){
   permutation(str,"");
}
void permutation(String str, String prefix){
  if(str.length()==0){
    System.out.println(prefix);
  } else{
    for(int i=0;i<str.length();i++){
        String rem=str.substring(0,i)+str.substring(i+1);
         permutation(rem,prefix+str.charAt(i));
    }
  }
}

. Я немного запутался, пытаясь думать об этом питонически. Я понял, что первая функция перестановки принимает строку и вызывает вторую функцию перестановки, которая выполняет всю работу. Однако не является ли вторая перестановка повторным выделением первой функции перестановки? Как java распознает и использует первую функцию перестановки? и не перезаписать это?

Ответы [ 4 ]

2 голосов
/ 10 января 2020

Как java распознает и использует первую функцию перестановки?

Когда вы вызываете метод, Java увидит, что вы пытаетесь передать в него. Основываясь на передаваемых вами аргументах, он решит, какую «версию» метода вы пытаетесь использовать.

Как уже говорили другие - это перегрузка метода

0 голосов
/ 10 января 2020

Чтобы объяснить, что такое семантика, нам нужно взглянуть на то, как дифференцируются Java методы.

В Java метод идентифицируется его сигнатурой. JLS §8.4.2 указывает, что

Два метода имеют одинаковую подпись, если они имеют одинаковые имена и типы аргументов.

Важно отметить является то, что тип возвращаемого значения метода не часть сигнатуры метода. Таким образом, если бы вы написали:

public class Foo {
    void bar(String baz) {
    }

    String bar(String baz) {
    }
}

Оба метода имели бы одинаковую подпись. В Java это приведет к ошибке компиляции, поскольку в одном классе нельзя использовать два метода с одинаковой сигнатурой.

Поведение изменится, если мы примем наследование в изображение:

public class Foo {
    void bar(String baz);
}

public class Zoo extends Foo {
    @Override
    void bar(String baz);
}

В этом случае класс Zoo переопределяет метод bar(...) класса Foo. Обратите внимание, что аннотация не отвечает за поведение и просто проверяет время компиляции, чтобы убедиться, что есть метод void bar(String baz) хотя бы в одном родительском классе.

В представленном коде есть два метода с одинаковым именем , но разные подписи. Это называется Перегрузка в Java. Таким образом, метод трактуется как не «равный». Вы можете переименовать один из этих методов, и они не будут более или менее «равными».

Чтобы сделать вещи еще более странными, если методы перегружены, подпись для вызываемого метода создается во время компиляции. Это означает, что могут рассматриваться только параметры типа stati c. Давайте посмотрим на следующий код и выясним, каков будет результат:

public class Test {
    public static void main(final String... args) {
        final String s = "foo";
        final Object o = s;
        print(s);
        print(o);
    }

    private static void print(final String s) {
        System.out.println("Called with String parameter");
    }

    private static void print(final Object o) {
        System.out.println("Called with Object parameter");
    }
}

Ideon demo

Теперь, что такое состояние c тип s? Это тип слева, где было объявлено s, поэтому вызывается print(final String s) и печатается "Called with String parameter". Что такое тип c stati o? Опять же, это тип слева, где o был объявлен, и, таким образом, print(final Object o) вызывается и "Called with Object parameter" распечатывается. Можно утверждать, что в этом тривиальном примере компилятор может выяснить, что тип o может быть только String, но основание этого поведения на способности компилятора распознавать типы во время компиляции делает его еще более запутанным .

0 голосов
/ 10 января 2020

В отличие от Python, в Java эти два объявления живут бок о бок - второе не заменяет первое. В Java правило примерно такое, что когда вы вызываете метод с несколькими определениями (он же «перегруженный» метод), * ​​1016 * будет искать тот, который лучше всего соответствует аргументам, с которым вы его вызвали, и запускать этот метод. Таким образом, permutation("hi") вызывает первую версию, а permutation("hi", "") вызывает вторую.

Принципиальное отличие здесь заключается в том, что в Python вы можете представить себе интерпретатора, читающего определения по одному и заменяющего его общее определение. permutation каждый раз, когда он получает новое определение. В Java вы должны думать об этом как о прочтении всех определений permutation одновременно и вызове наиболее подходящего для любого данного вызова.

(Следствие это то, что Java также проверяет во время компиляции, что каждая перегруженная версия метода может быть вызвана: например, если вы написали две версии permutation, каждая из которых взяла только строку в качестве аргумента, компилятор выдаст вам ошибка и не будет компилировать вашу программу вообще. В python вы просто получите второе определение.)

0 голосов
/ 10 января 2020

В java весь класс загружается перед выполнением метода.

Это означает, что второй метод загружается / готов до того, как первый метод будет выполнен, а первый метод загружен / готов до второй метод выполняется.

Это позволяет рекурсивно вызывать метод и вызывать метод, который будет объявлен позже.

Кроме того, метод перегружен .

В java возможно создание нескольких методов с одним и тем же именем в одном классе, если параметры разные. Методы будут рассматриваться как разные, отстраняясь от аргумента, передаваемого методу.

Другими словами, одно только имя не определяет, какой метод вызывается, но подпись , включая параметры (не возвращаемое значение)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...