A assinatura de um método em Java inclui seu tipo de retorno?

102

A assinatura do método em uma classe / interface Java inclui seu tipo de retorno?

Exemplo:

Java sabe a diferença entre esses dois métodos:

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

Ou talvez apenas o nome do método e a lista de parâmetros importem?

faressoft
fonte
7
A propósito, havia um bug no manuseio de genéricos no Java 6 que permitia ter os dois métodos, já que a JVM usa o tipo de retorno na assinatura e os chama seletivamente. Isso foi corrigido no Java 7. vanillajava.blogspot.co.uk/2011/02/…
Peter Lawrey

Respostas:

146

Citando do Oracle Docs :

Definição: dois dos componentes de uma declaração de método compreendem a assinatura do método - o nome do método e os tipos de parâmetro.

insira a descrição da imagem aqui

Já que a pergunta foi editada para incluir este exemplo:

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

Não, o compilador não saberá a diferença, pois sua assinatura: myMethod(int param)é a mesma. A segunda linha:

    public char myMethod(int param) {}

lhe dará um erro: o método já está definido na classe , o que confirma ainda mais a afirmação acima.

Jops
fonte
Então você quer dizer que não podemos ter dois métodos na classe com o mesmo nome de método, os mesmos parâmetros com tipos de retorno diferentes?
Kasun Siyambalapitiya
6
@KasunSiyambalapitiya of cource, não podemos. Como o compilador saberia qual dos métodos chamar em um cenário como este foo.bar(baz);?
Kolyunya
@Jops, e se tivermos a palavra-chave throws? Também pertence à assinatura?
Akila Amarasinghe
19

A assinatura do método de classe em Java inclui o tipo de retorno?

Em Java, não, mas neste JVM ele faz, o que pode levar a uma confusão óbvia.

A assinatura do método de interface em Java inclui o tipo de retorno?

O mesmo que para métodos de classe.

Ou apenas o nome do método e a lista de parâmetros?

Nome do método e tipos de parâmetro para Java. Por exemplo, as anotações e nomes dos parâmetros não importam.

Peter Lawrey
fonte
1
O que você quer dizer com "Em Java não, mas em JVM sim." Você poderia explicar como no JVM?
Tarun Maganti
3
@TarunMaganti O JVM inclui o tipo de retorno na assinatura do método. Java como linguagem não.
Peter Lawrey
3
@xyz isso é algo que você pode ver lendo o código de bytes, mas não o código Java. Qualquer código de byte mostra isso.
Peter Lawrey
8

No nível do bytecode, o "tipo de retorno" faz parte da assinatura do método. Considere isto

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

no bytecode existem 2 métodos clone ()

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

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

eles diferem apenas pelo tipo de retorno.

Evgeniy Dorofeev
fonte
1
isso é enganoso, pois o método de instância implicitamente tem a instância como primeiro parâmetro. Uma vez pode pensar que om (a) é de fato m (o, a). Sendo assim, no caso de clone, o que faz diferença é o argumento e não o tipo de retorno.
Huy Le
7

A especificação da linguagem Java diz

Dois métodos têm a mesma assinatura se tiverem o mesmo nome e tipos de argumento.

portanto, Não, o tipo de retorno não faz parte da assinatura do método.

PermGenError
fonte
6

Em JAVA e em muitas outras linguagens, você pode chamar um método sem uma variável para conter o valor de retorno. Se o tipo de retorno for parte de uma assinatura de método, não há como saber qual método será chamado ao chamar sem especificar o valor de retorno de retenção da variável.

Huy Le
fonte
4

Bro, Em java, usamos para chamar métodos por seus nomes e seus parâmetros apenas para usá-los em nosso código, como

meu método (20, 40)

então, JAVA só procura por itens semelhantes que correspondam em sua declaração correspondente (nome + parâmetro), é por isso que a assinatura do método inclui apenas o nome e os parâmetros do método. :)

NIKHIL CHAURASIA
fonte
3

A assinatura do método é o nome e a lista de parâmetros apenas.

Ray Stojonic
fonte
3

não, em Java a assinatura do método não inclui o tipo de retorno, mas a declaração sim.

public             String         getString(String myString)

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

editado com base no feedback abaixo :)

Jeff Hawthorne
fonte
1
Não é isso que o JLS diz. É "o mesmo nome e tipos de argumento". O modificador de acesso e o nome do parâmetro também não fazem parte da assinatura do método.
Peter Lawrey
se for uma pergunta de teste, tudo bem, mas se eu estiver escrevendo um programa, não estou escrevendo public getString (), estou escrevendo public String getString ()
Jeff Hawthorne
1
O modificador de acesso, tipo de retorno e tipo (s) de lançamento não fazem parte da assinatura, por isso você não pode ter String method( String s )e estar Double method( String s )na mesma classe, por exemplo.
Ray Stojonic
2
Talvez você esteja confundindo method signaturecommethod declaration
Peter Lawrey
@Ray, gostaria de observar, escrevi minha resposta antes de ele editar a pergunta inicial, tudo o que ele perguntou foi se fazia parte da assinatura, queria ter certeza de que ele não estava tentando escrever um nome público () sem listar o tipo de retorno (verdade seja dita, ele poderia ter respondido sua própria pergunta apenas escrevendo um programa simples para testá-lo)
Jeff Hawthorne
2

O tipo de retorno não inclui a assinatura do método. Somente o nome do método e os parâmetros são definidos como assinatura do método.

Refferir: 'Métodos de definição' do Oracle Docs

Kandy
fonte
1

Usando AspectJ (org.aspectj.lang.reflect.MethodSignature), ele tem o tipo de retorno

Devnull
fonte
1

A ASSINATURA DO MÉTODO INCLUI O TIPO DE RETORNO.

O compilador o ignora quando precisa verificar se há duplicatas. Para Java é ilegal ter dois métodos com a assinatura diferindo apenas pelo tipo de retorno.

Tente isso:

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();
    }
}

Compile o projeto, vá para o diretório bin, copie o Caller.cass em algum lugar. Em seguida, altere o método chamado:

public int aMethod() {
    return 0;
}

Construa o projeto, você verá que Called.class e Caller.class têm um novo carimbo de data / hora. Substitua o Caller.class acima e execute o projeto. Você terá uma exceção:

java.lang.NoSuchMethodError: it.prova.Called.aMethod()Ljava/lang/String;
Lucio Menci
fonte
0

Se você tentar executar o código que mencionou no eclipse, terá uma resposta sobre quais elementos o compilador java procura para diferenciar entre os métodos java:

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

O erro gerado é: Método duplicado myMethod (int) no tipo Foo.

Nishant_Singh
fonte