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?


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.


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.


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.


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



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.


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. :)



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 :)


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


1

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


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;


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.