Czy sygnatura metody w Javie zawiera jej zwracany typ?

102

Czy sygnatura metody w klasie / interfejsie Java zawiera zwracany typ?

Przykład:

Czy Java zna różnicę między tymi dwiema metodami:

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

A może liczy się tylko nazwa metody i lista parametrów?

faressoft
źródło
7
Nawiasem mówiąc, wystąpił błąd w obsłudze typów generycznych w Javie 6, który pozwalał mieć obie metody, ponieważ JVM używa zwracanego typu w sygnaturze i wywołuje je selektywnie. Zostało to naprawione w Javie 7. vanillajava.blogspot.co.uk/2011/02/…
Peter Lawrey

Odpowiedzi:

146

Cytowanie z Oracle Docs :

Definicja: Dwa składniki deklaracji metody obejmują podpis metody - nazwę metody i typy parametrów.

wprowadź opis obrazu tutaj

Ponieważ pytanie zostało zredagowane w celu uwzględnienia tego przykładu:

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

Nie, kompilator nie rozpozna różnicy, ponieważ ich podpis: myMethod(int param)jest taki sam. Druga linia:

    public char myMethod(int param) {}

da ci błąd: metoda jest już zdefiniowana w klasie , co dodatkowo potwierdza powyższe stwierdzenie.

Jops
źródło
Więc masz na myśli, że nie możemy mieć dwóch metod w klasie o tej samej nazwie metody, tych samych parametrach z różnymi typami zwracanych wartości?
Kasun Siyambalapitiya
6
@KasunSiyambalapitiya oczywiście nie możemy. Skąd kompilator miałby wiedzieć, którą z metod wywołać w takim scenariuszu foo.bar(baz);?
Kolyunya
@Jops, a co jeśli mamy słowo kluczowe throws? Czy to też należy do podpisu?
Akila Amarasinghe
19

Czy sygnatura metody klasy w Javie zawiera zwracany typ?

W Javie tak nie jest, ale w tej JVM robi, co może prowadzić do oczywistego zamieszania.

Czy sygnatura metody interfejsu w Javie zawiera typ zwracany?

To samo, co w przypadku metod klasowych.

A może tylko nazwa metody i lista parametrów?

Nazwa metody i typy parametrów dla języka Java. Na przykład opisy parametrów i nazwy nie mają znaczenia.

Peter Lawrey
źródło
1
Co masz na myśli mówiąc „W Javie tak nie jest, ale w JVM tak”. Czy mógłbyś wyjaśnić, jak to działa w JVM?
Tarun Maganti
3
@TarunMaganti Maszyna JVM zawiera zwracany typ w sygnaturze metody. Java jako język nie.
Peter Lawrey,
3
@xyz to jest coś, co można zobaczyć, czytając kod bajtowy, ale nie kod Java. Pokazuje to dowolny kod bajtowy.
Peter Lawrey
8

Na poziomie kodu bajtowego „typ zwracany” jest częścią sygnatury metody. Rozważ to

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

w kodzie bajtowym są 2 metody clone ()

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

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

różnią się tylko zwracanym typem.

Evgeniy Dorofeev
źródło
1
jest to mylące, ponieważ metoda instancji niejawnie ma instancję jako pierwszy parametr. Ktoś może pomyśleć, że om (a) jest w rzeczywistości m (o, a). Jako taka w przypadku klonu, różnica polega na tym, że argument nie zwraca typu.
Huy Le,
7

Java Language Spec mówi

Dwie metody mają ten sam podpis, jeśli mają tę samą nazwę i typy argumentów.

w ten sposób Nie, zwracany typ nie jest częścią podpisu metody.

PermGenError
źródło
6

W języku JAVA i wielu innych językach można wywołać metodę bez zmiennej, aby przechowywać zwracaną wartość. Jeśli typ zwracany jest częścią sygnatury metody, nie ma sposobu, aby dowiedzieć się, która metoda zostanie wywołana podczas wywoływania bez określenia zmiennej przechowującej wartość zwracaną.

Huy Le
źródło
4

Bracie, w javie używamy do wywoływania metod według ich nazwy i parametrów tylko po to, aby użyć ich w naszym kodzie, np

myMethod (20; 40)

więc JAVA wyszukuje tylko podobne rzeczy pasujące do odpowiedniej deklaracji (nazwa + parametr), dlatego podpis metody zawiera tylko nazwę metody i parametry. :)

NIKHIL CHAURASIA
źródło
3

Podpis metody to tylko nazwa i lista parametrów.

Ray Stojonic
źródło
3

nie, w Javie sygnatura metody nie zawiera zwracanego typu, ale deklaracja zawiera.

public             String         getString(String myString)

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

zredagowano na podstawie poniższych opinii :)

Jeff Hawthorne
źródło
1
To nie jest to, co mówi JLS. Jest to „ta sama nazwa i typy argumentów”. Modyfikator dostępu i nazwa parametru również nie są częścią podpisu metody.
Peter Lawrey,
jeśli jest to pytanie testowe, to w porządku, ale jeśli piszę program, nie piszę public getString (), piszę public String getString ()
Jeff Hawthorne
1
Modyfikator dostępu, typ zwracany i rzuca typ (-y) nie są częścią podpisu, dlatego nie można mieć String method( String s )i Double method( String s )w tej samej klasie, na przykład.
Ray Stojonic
2
Być może mylisz się method signaturezmethod declaration
Peterem Lawreyem
@Ray, chciałbym zauważyć, napisałem swoją odpowiedź, zanim zredagował początkowe pytanie, zapytał tylko, czy jest to część podpisu, chciałem się upewnić, że nie próbował wpisać nazwy publicznej typ powrotu (prawdę mówiąc, mógł odpowiedzieć na swoje pytanie po prostu pisząc prosty program do jego przetestowania)
Jeff Hawthorne
2

Zwracany typ nie jest uwzględniany w sygnaturze metody, tylko nazwa metody i parametry są zdefiniowane jako sygnatura metody.

Reffer: Oracle Docs ' Defining Methods'

Kandy
źródło
1

Używając AspectJ (org.aspectj.lang.reflect.MethodSignature), ma zwracany typ

devnull
źródło
1

PODPIS METODY ZAWIERA TYP ZWROTU.

Kompilator ignoruje go, gdy musi sprawdzić, czy nie ma duplikatów. W Javie niedozwolone jest posiadanie dwóch metod z podpisem różniącym się tylko typem zwracanym.

Spróbuj tego:

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

Zbuduj projekt, przejdź do katalogu bin, skopiuj gdzieś plik Caller.cass . Następnie zmień wywołaną metodę:

public int aMethod() {
    return 0;
}

Zbuduj projekt, zobaczysz, że zarówno Called.class, jak i Caller.class mają nowy znacznik czasu. Zastąp plik Caller.class powyżej i uruchom projekt. Będziesz miał wyjątek:

java.lang.NoSuchMethodError: it.prova.Called.aMethod()Ljava/lang/String;
Lucio Menci
źródło
0

Jeśli spróbujesz uruchomić kod, o którym wspomniałeś na eclipse, będziesz miał odpowiedź na pytanie, jakie elementy kompilator java szuka dla rozróżnienia między metodami java:

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

Zgłoszony błąd to: Zduplikowana metoda myMethod (int) w typie Foo.

Nishant_Singh
źródło