E 'sicuro di silenzio ClassCastException cattura durante la ricerca di un valore specifico?
-
10-10-2019 - |
Domanda
Supponiamo che io sono l'attuazione di una raccolta differenziata - Considerate questo (incompleta) implementazione (un semplice esempio Set
sulla base di un array ordinato.):
import java.util.*;
public class SortedArraySet<E> extends AbstractSet<E> {
@SuppressWarnings("unchecked")
public SortedArraySet(Collection<E> source, Comparator<E> comparator) {
this.comparator = (Comparator<Object>) comparator;
this.array = source.toArray();
Arrays.sort(this.array, this.comparator);
}
@Override
public boolean contains(Object key) {
return Arrays.binarySearch(array, key, comparator) >= 0;
}
private final Object[] array;
private final Comparator<Object> comparator;
}
Ora creiamo un insieme di numeri interi
Set<Integer> s = new SortedArraySet<Integer>(Arrays.asList(1, 2, 3), null);
E prova se contiene alcuni valori specifici:
System.out.println(s.contains(2));
System.out.println(s.contains(42));
System.out.println(s.contains("42"));
La terza riga sopra lancerà una ClassCastException
. Non quello che voglio. Io preferirei per tornare false
(come HashSet
fa.)
posso ottenere questo comportamento cattura l'eccezione e il ritorno false:
@Override
public boolean contains(Object key) {
try {
return Arrays.binarySearch(array, key, comparator) >= 0;
} catch (ClassCastException e) {
return false;
}
}
Supponendo che la collezione source
è correttamente tipizzata ??em>, cosa potrebbe andare male se faccio questo?
Soluzione
Non credo che ci sia alcun problema con questo come il Javadoc per Collection.contains
afferma chiaramente che gettando un ClassCastException
is facoltativa.
L'unica problema che vedo è che se si dispone di un bug qualche parte non un'eccezione caso non sarebbe possibile individuare esso.
Altri suggerimenti
La classe TreeSet
fa gettare un ClassCastException
per argomenti incompatibili contains()
(incompatibili per la Comparator
utilizzato dal set). Quindi non v'è nulla di sbagliato in lanciando questa eccezione. Basta fare in modo di documentare che questo possa accadere.
E 'perfettamente legittimo lasciare un lancio CCE da contains (). Tuttavia, molte implementazioni di raccolta cattura che e falso ritorno, che io considero essere anche perfettamente legittimo, e in effetti è l'user-friendly comportamento più.
In equals () non si ha la scelta; devi prendere che CCE.
Facendo un'eccezione incontrollato dovrebbe sempre sentirsi sporca, ma a volte è la cosa giusta da fare.