Включает ли подпись метода в Java его возвращаемый тип?


102

Включает ли подпись метода в классе / интерфейсе Java его тип возвращаемого значения?

Пример:

Знает ли Java разницу между этими двумя методами:

public class Foo {
    public int  myMethod(int param) {}
    public char myMethod(int param) {}
}

Или, может быть, имеет значение только название метода и список параметров?


7
Кстати, в Java 6 была ошибка в обработке дженериков, которая позволяла использовать оба метода, поскольку JVM действительно использует возвращаемый тип в сигнатуре и вызывает их выборочно. Это было исправлено в Java 7. vanillajava.blogspot.co.uk/2011/02/…
Питер Лоури,

Ответы:


146

Цитата из Oracle Docs :

Определение: два компонента объявления метода включают сигнатуру метода - имя метода и типы параметров.

введите описание изображения здесь

Поскольку вопрос был отредактирован, чтобы включить этот пример:

public class Foo {
    public int  myMethod(int param) {}
    public char myMethod(int param) {}
}

Нет, компилятор не заметит разницы, так как их подпись: myMethod(int param)одинаковая. Вторая строка:

    public char myMethod(int param) {}

выдаст вам ошибку: метод уже определен в классе , что дополнительно подтверждает приведенное выше утверждение.


Значит, вы имеете в виду, что у нас не может быть двух методов в классе с одинаковым именем метода, одинаковыми параметрами с разными типами возврата?
Kasun Siyambalapitiya

6
@KasunSiyambalapitiya, конечно, мы не можем. Как компилятор узнает, какой из методов вызвать в подобном сценарии foo.bar(baz);?
Колюня

@Jops, а что, если у нас есть ключевое слово throws? Это тоже к подписи?
Акила Амарасингхе

19

Включает ли подпись метода класса в Java тип возвращаемого значения?

В Java этого не происходит, но в этой JVM это происходит, что может привести к очевидной путанице.

Включает ли подпись метода интерфейса в Java тип возвращаемого значения?

То же, что и для методов класса.

Или только название метода и список параметров?

Имя метода и типы параметров для Java. Например, не имеют значения аннотации и названия параметров.


1
Что вы имеете в виду, говоря «В Java нет, но в JVM есть?»? Не могли бы вы рассказать, как это работает в JVM?
Tarun Maganti

3
@TarunMaganti JVM включает тип возвращаемого значения в сигнатуру метода. Java как язык - нет.
Питер Лоури

3
@xyz это то, что вы можете увидеть, прочитав байтовый код, но не код Java. Любой байт-код показывает это.
Питер Лоури 06

8

На уровне байт-кода «тип возврата» является частью сигнатуры метода. Учти это

public class Test1  {
    public Test1 clone() throws CloneNotSupportedException {
        return (Test1) super.clone();
    }
}

в байт-коде есть 2 метода clone ()

public clone()LTest1; throws java/lang/CloneNotSupportedException 

public clone()Ljava/lang/Object; throws java/lang/CloneNotSupportedException 

они различаются только типом возвращаемого значения.


1
это вводит в заблуждение, поскольку метод экземпляра неявно имеет экземпляр в качестве первого параметра. Кто-то может подумать, что om (a) на самом деле есть m (o, a). Таким образом, в случае клонирования разница в типе аргумента, а не возвращаемого значения.
Huy Le


7

В JAVA и многих других языках вы можете вызвать метод без переменной для хранения возвращаемого значения. Если тип возвращаемого значения является частью сигнатуры метода, невозможно узнать, какой метод будет вызван при вызове, без указания переменной, содержащей возвращаемое значение.


7

Спецификация языка Java говорит

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

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


4

Братан, в java мы используем для вызова методов по их имени и параметрам только для того, чтобы использовать их в нашем коде, например

myMethod (20, 40)

Итак, JAVA ищет только аналогичный материал, соответствующий их соответствующему объявлению (имя + параметр), поэтому подпись метода включает только имя и параметры метода. :)



3

нет, в Java сигнатура метода не включает возвращаемый тип, но декларация включает.

public             String         getString(String myString)

^access modifier   ^return type   ^name    ^parameter type and name

отредактировано на основе отзывов ниже :)


1
JLS не об этом говорит. Это «одно и то же имя и типы аргументов». Модификатор доступа и имя параметра также не являются частью сигнатуры метода.
Питер Лоури

если это тестовый вопрос, это нормально, но если я пишу программу, я не пишу public getString (), я пишу public String getString ()
Джефф Хоторн,

1
Модификатор доступа, тип возвращаемого значения и тип (ы) бросков не являются частью сигнатуры, поэтому, например, у вас не может быть String method( String s )и Double method( String s )в том же классе.
Ray Stojonic

2
Возможно, вы method signaturemethod declaration
сбиты

@Ray, я хотел бы отметить, я написал свой ответ до того, как он отредактировал исходный вопрос, все, что он спросил, было ли это частью подписи, я хотел убедиться, что он не пытается написать публичное имя () без перечисления тип возвращаемого значения (по правде говоря, он мог бы ответить на свой вопрос, просто написав простую программу для его проверки)
Джефф Хоторн


1

Используя AspectJ (org.aspectj.lang.reflect.MethodSignature), он имеет возвращаемый тип


1

ПОДПИСЬ МЕТОДА ВКЛЮЧАЕТ ТИП ВОЗВРАТА.

Компилятор игнорирует это, когда ему нужно проверить дубликаты. Для Java незаконно иметь два метода с сигнатурой, отличающейся только типом возвращаемого значения.

Попробуй это:

public class Called {
    public String aMethod() {
        return "";
    }
}

public class Caller {
    public static void main(String[] main) {
        aMethod();
    }
    public static void aMethod() {
        Called x = new Called();
        x.aMethod();
    }
}

Соберите проект, перейдите в каталог bin, скопируйте куда- нибудь Caller.cass . Затем измените вызываемый метод:

public int aMethod() {
    return 0;
}

Постройте проект, вы увидите, что и Called.class, и Caller.class имеют новую метку времени. Замените Caller.class выше и запустите проект. У вас будет исключение:

java.lang.NoSuchMethodError: it.prova.Called.aMethod()Ljava/lang/String;


0

Если вы попытаетесь запустить код, который вы упомянули в eclipse, у вас будет ответ относительно того, какие элементы java-компилятор ищет для различения между java-методами:

class Foo {
    public int  myMethod(int param) {
        return param;}
    public char *myMethod*(int param) { //this line throws an error 
        return param;
    }
}

Вызывается ошибка: Дублировать метод myMethod (int) в типе Foo.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.