Natknąłem się na to pytanie w quizie,
public class MoneyCalc {
public void method(Object o) {
System.out.println("Object Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
Dane wyjściowe tego programu to „Wersja ciągu”. Ale nie byłem w stanie zrozumieć, dlaczego przekazanie wartości null do przeciążonej metody wybrało wersję łańcuchową. Czy null jest zmienną typu String wskazującą na nic?
Jednak gdy kod zostanie zmieniony na,
public class MoneyCalc {
public void method(StringBuffer sb) {
System.out.println("StringBuffer Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
zwraca błąd kompilacji, mówiąc: „Metoda metody (StringBuffer) jest niejednoznaczna dla typu MoneyCalc”
java
overloading
zakSyed
źródło
źródło
Odpowiedzi:
Odwołanie o wartości null można przekonwertować na wyrażenie dowolnego typu klasy. Więc w przypadku
String
jest to w porządku:String
Przeciążenie tutaj jest wybrany, ponieważ kompilator Javy wybiera najbardziej szczegółowych przeciążenia, jak na odcinku 15.12.2.5 z JLS . W szczególności:W drugim przypadku obie metody nadal mają zastosowanie, ale żadna z nich
String
nieStringBuffer
jest bardziej szczegółowa od drugiej, dlatego żadna metoda nie jest bardziej szczegółowa niż druga, stąd błąd kompilatora.źródło
Object
może przyjąć dowolny typ i zawinąć go w plikObject
, podczas gdyString
może wziąć tylko plikString
. W tym przypadkuString
jest bardziej konkretnym typem w porównaniu zObject
typem.question.method((String)null)
Ponadto JLS 3.10.7 deklaruje również, że „null” jest dosłowną wartością „typu null”. Dlatego istnieje typ zwany „null”.
Później JLS 4.1 stwierdza, że istnieje typ zerowy, którego nie można zadeklarować zmiennych, ale można go używać tylko poprzez literał zerowy. Później mówi:
Dlaczego kompilator zdecydował się rozszerzyć ją do String, można dobrze wyjaśnić w odpowiedzi Jona .
źródło
Możesz przypisać a
string
donull
wartości, aby była poprawna, a kolejność dla języka Java i większości języków programowania była dopasowana do najbliższego typu, a następnie do obiektu.źródło
Aby odpowiedzieć na pytanie w tytule:
null
nie jest ani a,String
ani anObject
, ale można przypisać odniesienie do jednego z nichnull
.Właściwie jestem zaskoczony, że ten kod nawet się kompiluje. Próbowałem wcześniej czegoś podobnego i otrzymałem błąd kompilatora z informacją, że wywołanie jest niejednoznaczne.
Jednak w tym przypadku wydaje się, że kompilator wybiera metodę znajdującą się najniżej w łańcuchu pokarmowym. Zakłada się, że potrzebujesz najmniej ogólnej wersji metody, aby ci pomóc.
Muszę sprawdzić, czy uda mi się wykopać przykład, w którym wystąpił błąd kompilatora w tym (pozornie) dokładnie tym samym scenariuszu ...]
EDYCJA: Rozumiem. W stworzonej przeze mnie wersji miałem dwie przeciążone metody akceptujące a
String
i anInteger
. W tym scenariuszu nie ma parametru „najbardziej szczegółowego” (jak wObject
iString
), więc nie można wybrać między nimi, inaczej niż w kodzie.Bardzo fajne pytanie!
źródło
Ponieważ typ String jest bardziej szczegółowy niż typ obiektu. Powiedzmy, że dodajesz jeszcze jedną metodę, która przyjmuje typ Integer.
Wtedy pojawi się błąd kompilatora mówiący, że wywołanie jest niejednoznaczne. Jak teraz mamy dwie równie specyficzne metody z tym samym priorytetem.
źródło
Kompilator Java daje większość typów klas pochodnych do przypisania wartości null.
Oto przykład, aby to zrozumieć:
wyjście: klasa B.
z drugiej strony:
Wynik: metoda fun (C) jest niejednoznaczna dla typu MyTest
Mam nadzieję, że pomoże to lepiej zrozumieć ten przypadek.
źródło
Źródło: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5
Koncepcja: Najbardziej szczegółowa metoda
Wyjaśnienie: Jeśli więcej niż jedna metoda składowa jest jednocześnie dostępna i ma zastosowanie do wywołania metody, konieczne jest wybranie takiej, która zapewni deskryptor dla wywołania metody w czasie wykonywania. W języku programowania Java obowiązuje zasada, że wybierana jest najbardziej szczegółowa metoda. Spróbuj rzutować wartość null na określony typ, a żądana metoda zostanie automatycznie wywołana.
źródło
Ja bym nie powiedział. NULL to stan, a nie wartość. Sprawdź ten link, aby uzyskać więcej informacji na ten temat (artykuł dotyczy SQL, ale myślę, że pomoże to również w rozwiązaniu Twojego pytania).
źródło
null
jest zdecydowanie wartością, zgodnie z definicją zawartą w JLS.