Posso converter o código a seguir para usar genéricos?
-
09-06-2019 - |
Pergunta
Estou convertendo uma aplicação para usar Java 1.5 e encontrei o seguinte método:
/**
* Compare two Comparables, treat nulls as -infinity.
* @param o1
* @param o2
* @return -1 if o1<o2, 0 if o1==o2, 1 if o1>o2
*/
protected static int nullCompare(Comparable o1, Comparable o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -1;
}
} else if (o2 == null) {
return 1;
} else {
return o1.compareTo(o2);
}
}
O ideal seria que o método pegasse dois Comparáveis do mesmo tipo, é possível converter isso e como?
Achei que o seguinte resolveria o problema:
protected static <T extends Comparable> int nullCompare(T o1, T o2) {
mas não conseguiu se livrar de um aviso no IntelliJ "Chamada não verificada para 'compareTo(T)' como membro do tipo bruto 'java.lang.Comparable'" na linha:
return o1.compareTo(o2);
Solução
Altere para:
protected static <T extends Comparable<T>> int nullCompare(T o1, T o2) {
Você precisa disso porque Comparable é em si um tipo genérico.
Outras dicas
Aqui está um caso estranho:
static class A {
...
}
static class B extends A implements Comparable<A> {
public int compareTo(A o) {
return ...;
}
}
Felizmente, códigos como o acima são raros, mas nullCompare() não suportará comparação de Bs, a menos que seja declarado que Comparable pode ser aplicado a T ou qualquer superclasse dela:
protected static <T extends Comparable<? super T>> int nullCompare(T o1, T o2) {
Mesmo que a maioria das pessoas nunca se beneficie do ajuste acima, ele pode ser útil ao projetar APIs para bibliotecas exportadas.
Não é possível editar, então tenho que postar minha resposta.
Você precisa declarar o parâmetro de tipo aninhado, pois Comparable é genérico.
protected static <T extends Comparable<? super T>> int nullCompare(T o1, T o2) {
Por favor, note que Comparável< ?super-T >, o que torna mais flexível.Você verá a mesma definição de método em Collections.sort
public static <T extends Comparable<? super T>> void sort(List<T> list) {
Não tenho certeza se generalizar esse método faz sentido.Atualmente o método funciona em qualquer tipo de Comparável;se você generalizá-lo, terá que implementá-lo (exatamente com o mesmo código) várias vezes.Às vezes é possível comparar dois objetos que não possuem um ancestral comum, e qualquer versão genérica não permitirá isso.
Ao adicionar genéricos você não adicionará nenhuma segurança ao código;quaisquer problemas de segurança ocorrerão na chamada para compareTo.O que eu sugeriria é simplesmente suprimir o aviso.Na verdade, não está avisando sobre nada útil.
Para torná-lo ainda mais geral, você pode até permitir que funcione para dois tipos diferentes.=P
/**
* Compare two Comparables, treat nulls as -infinity.
* @param o1
* @param o2
* @return -1 if o1<o2, 0 if o1==o2, 1 if o1>o2
*/
protected static <T> int nullCompare(Comparable<? super T> o1, T o2) {
if (o1 == null) {
if (o2 == null) {
return 0;
} else {
return -1;
}
} else if (o2 == null) {
return 1;
} else {
return o1.compareTo(o2);
}
}