Aby uzyskać najlepsze wyniki, należy użyć public static <T extends Comparable<? super T>> T max(T a, T b)
.
Problem z <T extends Comparable<?>>
polega na tym, że mówi się, że typ T jest porównywalny z pewnym typem, ale nie wiesz, jaki to typ. Oczywiście, zdrowy rozsądek dyktowałby, że klasa, która implementuje porównywalne, powinna być w stanie być porównywalna z samą sobą (tj. Być zdolna do porównania z obiektami własnego typu), ale nie ma żadnych przeszkód, aby klasa A mogła wdrożyć Comparable<B>
, gdzie A i B nie mają ze sobą nic wspólnego. <T extends Comparable<T>>
rozwiązuje ten problem.
Ale z tym jest subtelny problem. Załóżmy, że klasa X implementuje Comparable<X>
, a ja mam klasę Y, która rozszerza X. Więc klasa Y automatycznie implementuje Comparable<X>
przez dziedziczenie. Klasa Y nie może również implementować Comparable<Y>
, ponieważ klasa nie może zaimplementować interfejsu dwukrotnie z różnymi parametrami typu. Nie stanowi to problemu, ponieważ instancje Y są instancjami X, więc Y jest porównywalne ze wszystkimi instancjami Y. Problem polega jednak na tym, że nie można użyć typu Y z funkcją <T extends Comparable<T>> T max(T a, T b)
, ponieważ Y nie implementuje Comparable<Y>
. Granice są zbyt surowe.<T extends Comparable<? super T>>
rozwiązuje problem, ponieważ wystarczy, aby T było porównywalne z jakimś nadtypem T (który zawierałby wszystkie wystąpienia T). Przypomnijmy regułę PECS - producent extends
, konsument super
- w tym przypadku, Comparable
jest konsumentem (przyjmuje obiekt do porównania), więc super
ma sens.
Jest to granica typu używana przez wszystkie funkcje sortowania i zamawiania w bibliotece Java.
W bloku 'if (a == null)' nie ma potrzeby stosowania zagnieżdżonej klauzuli if. Zmniejszenie bloku do 'return b;' daje taki sam wynik ('null', gdy' b' ma wartość 'null',' b' w innym przypadku). – benjamin
Zobacz [org.apache.commons.lang3.ObjectUtils.compare] (https://commons.apache.org/proper/commons-lang/javadocs/api-3.6/org/apache/commons/lang3/ObjectUtils.html# compare-TT-) –